[Haskell-beginners] Pointfree expeiments

Paul Sargent psarge at gmail.com
Thu Nov 25 05:55:39 EST 2010


Thanks Stephen,

On 25 Nov 2010, at 09:12, Stephen Tetley wrote:

> On 25 November 2010 01:44, Paul Sargent <psarge at gmail.com> wrote:
> [SNIP]
> 
>> 
>> I'm aware that 'ap' is related the liftM, but what is this monad, and why are we working in a monad at all?
>> 
>> ...and surely this isn't the same as the original code as we now have a different type signature?_______________________________________________
> 
> Its the Reader monad.
> 
> [...]

> Pointfree is presumably introducing it because it can't find
> elementary definitions that are only functional types [...] 

> In one stroke it is a use of the 'w' combinator:

> -- | W combinator - warbler - elementary duplicator.
> w :: (r1 -> r1 -> ans) -> r1 -> ans
> w f x = f x x

> Monadic ap for the Reader monad corresponds to the Starling 's'
> combinator:

> starling :: (r1 -> a -> ans) -> (r1 -> a) -> r1 -> ans
> starling f g x = f x (g x)



The Starling and Warbler combinators make perfect sense to me. I'm still trying to see how ap in the Reader Monad is equivalent to Starling. I think this is exposing some holes in my Haskell knowledge, so I'm using it as a learning exercise.

We use them in the same way, and we're saying they're equivalent:

    let f x = starling (+) id
    let g x = ap (+) id

Yet, they have quite different type signatures.

    starling :: (r1 -> a -> ans) -> (r1 -> a) -> r1 -> ans
    ap       :: (Monad m) => m (a -> b) -> m a -> m b

So, my first question is what makes haskell choose the Reader monad in this case?

Secondly, (+) is a function of two arguments, and id a function of one. This binds naturally with starling, but not apparently with ap. Apparently ap wants a single argument function within a monad as it's first argument, so to me (+) shouldn't satisfy. I suspect the answer to this has something to do with my first question.

Digging a little deeper, I decided to look at the definition of ap:

    ap =  liftM2 id
    
    liftM2  :: (Monad m) => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
    liftM2 f m1 m2 = do { x1 <- m1; x2 <- m2; return (f x1 x2) }

liftM2 makes sense to me, but again we seem to have a mismatch of types. liftM2 wants a two argument function for it's first argument, but ap provides id. I'm finding myself tumbling further and further down the rabbit hole.

Paul




More information about the Beginners mailing list