我要创造我自己的单子。这是我写的:

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)

但是,这不工作。 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'

请告诉我错?


我想要做的计算而i为低于n。 N乘我应该是常数,还不知道如何做到这一点是正确的。它应该是一些混合的国家,也许。如果你有一些建议随时与我分享吧:P

有帮助吗?

解决方案

关于return

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

所以return采用类型a的参数,并返回型m a的东西。在这种情况下是m LeafConType,所以返回LeafConType a

现在假设我们通过True。然后a = Bool,因此,返回类型必须是LeafConType Bool。然而,可以定义:

return = LeafCon

所以,return True变得LeafCon True。但是,这是不允许的,因为类型定义LeafConType状态,即

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

因此,对于LeafConType Bool的参数LeafCon必须具有类型(Bool, Int, Int),不只是Bool。而这正是编译错误方法:a不能一样(a, Int, Int)。幽州:

  

我想要做的计算而in更低。

这意味着你将需要一些默认值in,否则这将是无法界定return。如果双方都默认为零,则你可以定义:

return a = LeafCon (a, 0, 0)

关于(>>=)

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

现在看看你的实现(稍有不同的符号,同样的想法):

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

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

<强> 能这种类型的计算反正表示为单子?

其他提示

>>=return不满足类型中指定的功能所需要的由Monad

return :: a -> LeafConType a

鉴于声明

return = LeafCon

你给该函数的不兼容的类型

return :: (a, Int, Int) -> LeafConType a

return 42声明将因此会不可能在你的单子。

我不明白你的单子应该不惜一切做什么。 先来看看简单,工作单子!

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

instance Monad Maybe where
    return = Just
    (Just x) >>= f = f x
    Nothing >>= f = Nothing

从你的你希望你的单子做什么的描述来看,我觉得你想要的东西有点像这样:

data LeafConType a = LeafCon { runLeafCon' :: Int -> Int -> (Maybe a, Int, Int) }

runLeafCon :: Int -> Int -> LeafConType a -> Maybe a
runLeafCon i n lc = let (t, _, _) = runLeafCon' lc i n in t

getI :: LeafConType Int
getI = LeafCon $ \i n -> (Just i, i, n)

getN :: LeafConType Int
getN = LeafCon $ \i n -> (Just n, i, n)

setI :: Int -> LeafConType ()
setI i = LeafCon $ \_ n -> (Just (), i, n)

setN :: Int -> LeafConType ()
setN n = LeafCon $ \i _ -> (Just (), i, n)

instance Monad LeafConType where
    return t = LeafCon $ \i n -> if (i < n) 
                                 then (Just t, i, n) 
                                 else (Nothing, i, n)

    (LeafCon k) >>= f = 
        LeafCon $ \i n -> 
            let (t, i', n') = k i n
            in case t of
                 Nothing -> (Nothing, i', n')
                 (Just t') -> if (i' < n')
                              then runLeafCon' (f t') i' n'
                              else (Nothing, i, n)


example :: Int -> LeafConType ((), Int)
example x = do 
  i <- getI
  m <- setI (i + x)
  return (m, i + x)

一些示例:

*Main> runLeafCon 2 10 $ example 4
Just ((),6)
*Main> runLeafCon 2 10 $ example 8
Nothing
*Main> runLeafCon 2 10 $ example 7
Just ((),9)

我把这个在一起很快,这是相当丑陋,我还没有检查,看它是否服从任何的单子法律,所以在使用后果自负! :)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top