2015-09-06 1 views
1

У меня есть некоторые функции траверса/аксессоров работать с моим сетчатым типом:Pointfree преобразование

cell :: Mesh a -> Int -> Maybe (Cell a) 
neighbour :: Mesh a -> Int -> Cell a -> Maybe (Cell a) 
owner :: Mesh a -> Cell a -> Maybe (Cell a) 

Чтобы избежать прохождения сетки для каждой функции и для обработки терпит неудачу, я создал одноместный версию из них с помощью этого соединения монады:

type MMesh a b = MaybeT (State (Mesh a)) b 

Итак, у меня есть такие монадические аксессоры:

getMesh = get :: MMesh a (Mesh a) -- just to remove type declarations 

cellM id = getMesh >>= (MaybeT . return) <$> (\m -> cell m id) 
neighbourM idx cell = getMesh >>= (MaybeT . return) <$> (\m -> neighbour m idx cell) 
ownerM cell = getMesh >>= (MaybeT . return) <$> (\m -> owner m cell) 

Они, очевидно, следуют тому же Патти р-н и я был бы рад, чтобы переместить общую часть в некоторой внешней функции, скажем liftMesh переписать код выше как:

cellM = liftMesh cell 
neighbourM = liftMesh neighbour 
ownerM - liftMesh owner 

Но это первый нуждается в функции должна быть переписана в стиле pointfree опустить переменное число аргументов. И вот где я застрял, так может ли кто-нибудь помочь преобразовать это в pointfree или найти другие способы достижения одного и того же результата?

Upd: добавление полный текст здесь: http://pastebin.com/nmJVNx93

+1

Пожалуйста, сделайте свой код самодостаточным. В частности, добавьте свои операторы импорта и определения для 'Mesh',' Cell' и т. Д. Пользователям будет проще убедиться, что их версии без ограничений. – Jubobs

+1

Вы пробовали инструмент pointfree? –

+0

Благодарим вас за идею, но кажется, что это слишком сложно для инструмента без очков или я что-то делаю неправильно –

ответ

1

Просто использовать gets, который возвращает проекцию состояния, заданного произвольной функции на нем, и MaybeT:

cellM ix = MaybeT (gets (\m -> cell m ix)) 

neighbourM ix c = MaybeT (gets (\m -> neighbour m ix c)) 

owner c = MaybeT (gets (\m -> owner m c)) 

(NB: I рекомендовать не называть вещи id. Функция id слишком важна, что делает столкновение имени очень запутанным.)

Чтобы сделать это больше pointfr ee, переупорядочивайте аргументы своих функций по мере необходимости. Например:

cell :: Int -> Mesh a -> Maybe (Cell a) 

cellM ix = MaybeT (gets (cell ix)) 

(Вы можете пройти весь путь и писать cellM = MaybeT . gets . cell вместо этого, но я чувствую, что будет слишком неясными, что cellM делает.)

PS: Учитывая то, что вы используете State, шансы вы также интересуются функциями, которые изменяют сетку. Если вы этого не сделаете, то Reader будет более подходящим, чем State.

+0

Однако переупорядочение аргументов может быть не вариантом. – Jubobs

+0

@Jubobs Если это не так, то не нужно :) (Или используйте 'flip', но мне действительно не хочется добавлять это к ответу. Это становится уродливым ...) – duplode

+0

Да, он быстро уродливый , Я просто поддразнивал. – Jubobs