Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在haskell中创建单子_Haskell_Monads - Fatal编程技术网

在haskell中创建单子

在haskell中创建单子,haskell,monads,Haskell,Monads,我想创建我自己的单子。这是我写的: 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) 但这

我想创建我自己的单子。这是我写的:

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为
>=
返回指定的函数不满足
Monad
所需的类型:

return :: a -> LeafConType a
根据声明

return = LeafCon
您为函数指定了不兼容的类型

return :: (a, Int, Int) -> LeafConType a
因此,像
return 42
这样的语句在monad中是不可能的

我根本不明白你的单子该怎么做。 首先看一看简单、有效的单子

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

instance Monad Maybe where
    return = Just
    (Just x) >>= f = f x
    Nothing >>= f = Nothing
关于
返回
: 因此
return
接受类型为
a
的参数,并返回类型为
ma
的内容。在本例中,
m
LeafConType
,因此返回
LeafConType a

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

return = LeafCon
因此,
返回真值
变为
LeafCon真值
。但这是不允许的,因为
LeafConType
的类型定义声明

data LeafConType a = LeafCon (a, Int, Int)
因此,对于
LeafConType Bool
而言,
LeafCon
的参数必须具有类型
(Bool,Int,Int)
,而不仅仅是
Bool
。这就是编译错误的意思:
a
不能与
(a,Int,Int)
相同。你说:

我想在
I
低于
n
时进行计算

这意味着您将需要
i
n
的一些默认值,否则将无法定义
return
。如果默认情况下两者均为零,则可以定义:

return a = LeafCon (a, 0, 0)
关于
(>>=)
: 现在看看您的实现(符号略有不同,想法相同):

我们在这里看到,
lc
i>=n
时返回。但是
lc
属于
leafcontypea
类型,而
f
是一个函数,它可以为任何
b
返回
leafcontypeb
类型的值。结果可能是
b
不等于
a
,因此这些类型不匹配。总之,你必须认真地问自己一个问题:


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

从您对monad所做的描述来看,我认为您需要类似这样的东西:

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)

我很快就把它拼凑起来了,它相当难看,而且我还没有检查它是否遵守任何单子定律,所以使用它会有危险

我应该早10秒按下那个按钮…;)我认为可以,也许不是这样,但这是可能的。它应该携带诸如状态monad之类的信息,以及诸如monad之类的结束计算。您考虑过使用状态转换器吗。查看
StateT
error
。不要忘记
MaybeT
Prelude> :t (>>=)
(>>=) :: (Monad m) => m a -> (a -> m b) -> m b
lc@(LeafCon (t, i, n)) >>= f | i >= n    = lc 
                             | otherwise = f t
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)