我正试图用Monad编写一个Haskell“猜数字”游戏程序,但我被塞了下来:
我试过简单的单曲:
data SM a = SMN (S -> (a, S))
instance Monad SM where
SMN c1 >>= fc2 = SMN (\s0 -> let (r, s1) = c1 s0 in
let SMN c2 = fc2 r in
c2 s1)我需要在元组(a,S)的“IO端”执行IO任务,也就是说,我尝试执行以下操作:
SMN c1 >>= fc2 = SMN (\s0 -> let (r, s1) = c1 s0 in
let SMN c2 = fc2 r in
let (r1, s2) = c2 s1 in
let r2 = r1 >>= (\_ -> r) in
(r2, s2))简而言之,我要定义的bind操作符与原始状态monad相同,只不过我们将r1和接受参数为r的常量函数绑定在一起(因此这两个动作是链接在一起的)。但是ghc告诉我a是一个刚性的变量..。那是什么意思?我不能在一个绑定操作符中使用另一个绑定操作符吗?
如果是,那么有什么方法可以实现这样的bind操作符呢?多么?
因为我是哈斯克尔的新手(我想我可能在这个函数上出了个错误。)
\_ -> r),欢迎任何意见和参考,谢谢。
我对数据类型SM和类型构造函数SMN使用了不同的符号,以区分它们。
发布于 2015-02-21 17:38:26
(>>=)的类型是:
Monad m => m a -> (a -> m b) -> m b由于您正在为SM编写实例,因此实例中的绑定类型为
SM a -> (a -> SM b) -> SM b注意,a和b都是完全不受限制的类型变量。这意味着,无论我选择了哪种类型,您所提供的任何实现都必须有效。特别是,我可以为a和b选择a和b。
SM Int -> (Int -> SM Int) -> SM Int现在很清楚为什么您的实现是不好的:它将尝试将Int视为一元操作,并在其上调用(>>=)。
如果您希望能够在绑定中执行一元操作,则必须以某种方式讨论类型中的monad;例如,一种标准的方法是定义
data SMT m a = SMT (S -> m (a, S))并举例如下:
instance Monad m => Monad (SMT m) where -- ...然后,如果您愿意的话,可以使用普通的SM作为嵌套monad来恢复正常的Identity。
https://stackoverflow.com/questions/28647563
复制相似问题