Search code examples
haskellpointfree

Pointfree conversion


I have some traverse/accessor functions to work with my mesh type:

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

To avoid passing mesh to each function and to handle fails I've created monadic version of them via this compound monad:

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

So, I have such monadic accessors:

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)

They obviously follow the same pattern and I would be glad to move common part to some external function, say liftMesh to rewrite the code above as:

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

But this first needs the functions to be rewritten in pointfree style to omit variable number of arguments. And that's where I'm stuck, so could anyone help to convert this to pointfree or find other ways achive the same result?

Upd: adding the full text here: http://pastebin.com/nmJVNx93


Solution

  • Just use gets, which returns a projection of the state specified by an arbitrary function on it, and 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))
    

    (N.B.: I recommend not naming things id. The standard id function is too important, which makes the name clash very confusing.)

    To make that more pointfree, reorder the arguments of your functions as appropriate. For instance:

    cell :: Int -> Mesh a -> Maybe (Cell a)
    
    cellM ix = MaybeT (gets (cell ix))
    

    (You could go all the way and write cellM = MaybeT . gets . cell instead, but I feel that would excessively obscure what cellM does.)

    P.S.: Given that you are using State, odds are you are also interested in functions that modify a mesh. If you aren't, however, Reader would be more appropriate than State.