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的就是afooa
,它相当于(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的就是afooa
,它相当于(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)