在haskell中创建monad

qba*_*qba 10 monads haskell

我想创建自己的monad.这就是我写的:

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)
Run Code Online (Sandbox Code Playgroud)

但这不行.Ghc说:

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'
Run Code Online (Sandbox Code Playgroud)

那有什么不对吗?


当我低于n时,我想做计算.n应该是常数我还不知道如何做到这一点.它应该是State和Maybe的混合体.如果您有任何建议,请随时与我分享:P

Ste*_*202 12

关于return:

Prelude> :t return
return :: (Monad m) => a -> m a 
Run Code Online (Sandbox Code Playgroud)

因此return接受类型的参数a,并返回类型的东西m a.在这种情况下mLeafConType,所以LeafConType a返回.

现在假设我们通过了True.那么a = Bool,返回类型必须是LeafConType Bool.但是,您定义:

return = LeafCon
Run Code Online (Sandbox Code Playgroud)

所以,return True成为LeafCon True.但这是不允许的,因为LeafConType状态的类型定义

data LeafConType a = LeafCon (a, Int, Int)
Run Code Online (Sandbox Code Playgroud)

因此,LeafConType Bool对于LeafCon必须具有类型的参数(Bool, Int, Int),不仅仅是Bool.这就是编译错误的含义:a不能相同(a, Int, Int).你说:

我想在i低于的时候做计算n.

这意味着你将需要一些默认值in,否则这将是无法界定的return.如果默认情况下它们都为零,那么您可以定义:

return a = LeafCon (a, 0, 0)
Run Code Online (Sandbox Code Playgroud)

关于(>>=):

Prelude> :t (>>=)
(>>=) :: (Monad m) => m a -> (a -> m b) -> m b
Run Code Online (Sandbox Code Playgroud)

现在看看你的实现(略有不同的表示法,相同的想法):

lc@(LeafCon (t, i, n)) >>= f | i >= n    = lc 
                             | otherwise = f t
Run Code Online (Sandbox Code Playgroud)

我们在这里看到的是,lc当它返回时i >= n.但lc是类型的LeafConType a,而f是可以返回类型的值的函数LeafConType b,对于任何 b.因此,它可能b不等于a,因此这些类型不匹配.总之,你真的要问自己一个问题:

  这种类型的计算是否可以表示为monad?


Dar*_*rio 7

您指定的功能>>=return不符合所要求的类型Monad:

return :: a -> LeafConType a
Run Code Online (Sandbox Code Playgroud)

鉴于声明

return = LeafCon
Run Code Online (Sandbox Code Playgroud)

你赋予函数不兼容的类型

return :: (a, Int, Int) -> LeafConType a
Run Code Online (Sandbox Code Playgroud)

return 42因此,你的monad中不可能有这样的陈述.

我不明白你的monad应该做什么.首先来看看简单,有效的monad!

instance Monad [] where
    (>>=) = concatMap
    return a = [a]

instance Monad Maybe where
    return = Just
    (Just x) >>= f = f x
    Nothing >>= f = Nothing
Run Code Online (Sandbox Code Playgroud)