Class 生成monad类的延续monad包装实例

Class 生成monad类的延续monad包装实例,class,haskell,instance,monads,continuations,Class,Haskell,Instance,Monads,Continuations,我有类型Foo,它是围绕conta的简单包装。我想让Foo键入Monad类的一个实例。我试试这个: import Control.Monad.Cont newtype Foo a = Foo {unFoo :: Cont a a} instance Monad Foo where return = Foo . return Foo inner >>= func = Foo (inner >>= newFunc) where newFun

我有类型
Foo
,它是围绕
conta
的简单包装。我想让
Foo
键入
Monad
类的一个实例。我试试这个:

import Control.Monad.Cont

newtype Foo a = Foo {unFoo :: Cont a a}

instance Monad Foo where
    return = Foo . return
    Foo inner >>= func = Foo (inner >>= newFunc)
        where newFunc x = (unFoo $ func x)
但我有一个错误:

Couldn't match type `a' with `b'
  `a' is a rigid type variable bound by
      the type signature for >>= :: Foo a -> (a -> Foo b) -> Foo b
      at Classes.hs:7:5
  `b' is a rigid type variable bound by
      the type signature for >>= :: Foo a -> (a -> Foo b) -> Foo b
      at Classes.hs:7:5
Expected type: ContT b Data.Functor.Identity.Identity a
  Actual type: Cont a a
In the first argument of `(>>=)', namely `inner'
In the first argument of `Foo', namely `(inner >>= newFunc)'
In the expression: Foo (inner >>= newFunc)

如何正确地为
Foo
添加
Monad
实例?

您不能将
Foo
添加到
Monad

首先,让我们指出,
fooa
是一种精心编写
(a->a)->a
的方式

runFoo :: Foo a -> ((a -> a) -> a)
runFoo = runCont . unFoo

foo :: ((a -> a) -> a) -> Foo a
foo = Foo . cont
只有一种方法可以定义
(>>=)::fooa->(a->foob)->foob
。我们需要一个
a
传递到箭头
a->foob
。我们唯一拥有
a
s的就是a
fooa
,它相当于
(a->a)->a
。如果我们能够提供类型为
a->a
的函数,它将为我们提供
a
,其中只有一个,
id
。因此,我们获取
a
的唯一选择是传递
id

instance Monad Foo where
    return = Foo . return
    ma >>= f = f (runFoo ma id)
这将使一条
Monad
法则失败,
m>>=返回≡ m
。我们将在
Foo
中编写一个反例

counterExample :: Foo Int
counterExample = foo (\f -> if f 0 == 1 then 7 else 13)
当传递标识函数
id
时,反例会导致
13
,但当传递后续函数
(+1)
时,只会导致
7

由于
Monad
定律,
counterExample'=counterExample>>=return
应该与
counterExample
完全相同,但不能完全相同
>=
已将
id
传递给函数,并且仅
返回结果,
13
<代码>反例'
反例的作用不同

let counterExample' = counterExample >>= return
print $ runFoo counterExample' id
print $ runFoo counterExample' (+1)

13
14

由于
>=
只有一个可能的实现,而且它是不正确的,
Foo
没有正确的
Monad
实例,因此不能将
Foo
变成
Monad

counterExample :: Foo Int
counterExample = foo (\f -> if f 0 == 1 then 7 else 13)
首先,让我们指出,
fooa
是一种精心编写
(a->a)->a
的方式

runFoo :: Foo a -> ((a -> a) -> a)
runFoo = runCont . unFoo

foo :: ((a -> a) -> a) -> Foo a
foo = Foo . cont
只有一种方法可以定义
(>>=)::fooa->(a->foob)->foob
。我们需要一个
a
传递到箭头
a->foob
。我们唯一拥有
a
s的就是a
fooa
,它相当于
(a->a)->a
。如果我们能够提供类型为
a->a
的函数,它将为我们提供
a
,其中只有一个,
id
。因此,我们获取
a
的唯一选择是传递
id

instance Monad Foo where
    return = Foo . return
    ma >>= f = f (runFoo ma id)
这将使一条
Monad
法则失败,
m>>=返回≡ m
。我们将在
Foo
中编写一个反例

counterExample :: Foo Int
counterExample = foo (\f -> if f 0 == 1 then 7 else 13)
当传递标识函数
id
时,反例会导致
13
,但当传递后续函数
(+1)
时,只会导致
7

由于
Monad
定律,
counterExample'=counterExample>>=return
应该与
counterExample
完全相同,但不能完全相同
>=
已将
id
传递给函数,并且仅
返回结果,
13
<代码>反例'
反例的作用不同

let counterExample' = counterExample >>= return
print $ runFoo counterExample' id
print $ runFoo counterExample' (+1)

13
14
由于
>=
只有一个可能的实现,而且它不正确,
Foo
没有正确的
Monad
实例

counterExample :: Foo Int
counterExample = foo (\f -> if f 0 == 1 then 7 else 13)