Alex Rivera | Logout

Creating monads in haskell

Asked 2009-11-22T17:58:35.860
11

I want to create my own monad. This is what i wrote:

data LeafConType a = LeafCon (a,Int,Int)

instance Monad (LeafConType ) where
return = LeafCon 
lc@(LeafCon (t,i,n)) >>= f = if i>=n
                                then lc
                                else f (t,i,n)

But this dont work. Ghc says:

leafcon.hs:26:1:
    Occurs check: cannot construct the infinite type: a = (a, Int, Int)
    When generalising the type(s) for `return'
    In the instance declaration for `Monad LeafConType'

leafcon.hs:27:1:
    Occurs check: cannot construct the infinite type: a = (a, Int, Int)
    When generalising the type(s) for `>>='
    In the instance declaration for `Monad LeafConType'

Whats wrong with that?


I want to do calculations while i is lower than n. n should be constants by I don't know yet how to do this correct. It should be some mix of State and Maybe. If you have some advices feel free to share it with me:P

Edit
Report

1 Answer

14

About return:

Prelude> :t return
return :: (Monad m) => a -> m a 

So return takes an argument of type a, and returns something of type m a. In this case m is LeafConType, so LeafConType a is returned.

Now suppose that we pass True. Then a = Bool, so the return type must be LeafConType Bool. However, you define:

return = LeafCon

So, return True becomes LeafCon True. But that is not allowed, because the type definition of LeafConType states that

data LeafConType a = LeafCon (a, Int, Int)

So for LeafConType Bool the argument to LeafCon must have type (Bool, Int, Int), not just Bool. And that is what the compile error means: a cannot be the same as (a, Int, Int). You state:

I want to do calculations while i is lower than n.

This means that you will need some default values for i and n, for otherwise it will be impossible to define return. If both of them are zero by default, then you could define:

return a = LeafCon (a, 0, 0)

About (>>=):

Prelude> :t (>>=)
(>>=) :: (Monad m) => m a -> (a -> m b) -> m b

Now look at your implementation (slightly different notation, same idea):

lc@(LeafCon (t, i, n)) >>= f | i >= n    = lc 
                             | otherwise = f t

What we see here, is that lc is returned when i >= n. But lc is of type LeafConType a, while f is a function w

answered 2009-11-22T18:17:03.323

Your Answer