我是Haskell,函数式语言和monad的新手。
我已经把这个问题搞了一个月左右。我读过了解到您有一个haskell,并且一直在努力地尝试创建我的haskell网站。
但是有些东西困扰着我:单子抽象。如果我理解正确,那么monads是可以排序的“数据容器”。例如,我可以使用“ >> =”对其进行“解压缩”,然后我将在“幕后”进行更多工作,因此,如果我没有monad定义,则必须猜测如何解压缩。
例如:
我们有清单monad,将其拆包将对其元素进行排序
[1,2,3] >>= return . (+1) -- gives back [2,3,4]
或更复杂的monad,例如那些示例中的writer:Log Writer Monad
或者我可能有一个webWriter monad,它针对其值的每个“解压缩”都会向一个远程服务器发送一个请求(我不确定这一点,但是我试图给出一个极端的例子)
我的问题是:仅通过查看monad用户界面(我猜是类型定义),我能否说出apply函数('>> =','applyLog')在幕后做什么?
希望我能很好地解释自己。
谢谢,奥伦。
尽管(>>=)
仅通过查看界面就无法知道对特定monad有什么用,但是有些法律必须遵守每个monad才能构成“适当的” monad。并且限制了return
和的可能实现(>>=)
。该单子法律如下:
return a >>= f
等于f a
m >>= return
等于m
(m >>= f) >>= g
等于m >>= (\x -> f x >>= g)
例如,如果return
为List monad定义为\x -> [x,x]
而不是\x -> [x]
,那将违反左身份定律。return 5 >>= \x -> [x+1]
将与有所不同(\x -> [x+1]) 5
。
同样,并非所有monad都可以直观地理解为某种“容器”。容器类比适用于List和Maybe,但例如Reader呢?读者值并没有真正“包含”任何内容。相反,它是对依赖于外部不变环境的计算的描述。
Monad是实现monad接口并遵守monad法律的任何内容。
编辑:作为如何直觉单子实例做什么给定类型的一个例子,考虑Data.Stream.Infinite.Stream从流包。流就像列表,只是它们总是无限的。
流有一个Monad实例。什么会return
和(>>=)
在这种情况下怎么办?
return
具有类型a -> Stream a
。这种类型的唯一可能函数是返回作为参数传递的值的无限重复的函数。
(>>=)
比较棘手。它具有类型Stream a -> (a -> Stream b) -> Stream b
。这种类型的一个可能函数是采用第一个参数的头部并将其应用于第二个参数,并返回结果流的函数。s >>= f = f $ head s
。
另一个可能的实现的(>>=)
。将型的功能应用a -> Stream b
到每一原始流的元素,得到类型的中间结果Stream (Stream b)
,然后流的流以某种方式折叠成一个单一的Stream b
值。怎么做?您可以简单地取无限正方形的对角线!
哪个版本(>>=)
与monad法律兼容?第一个肯定不会,因为它破坏了正确的身份。的结果1,2,3,4... >>= return
将是1,1,1,1...
。第二种实现尊重正确的身份(您知道为什么吗?),这使我们更加确信这可能是实现(>>=)
流的正确方法。当然,您需要所有法律的实际证明才能确定!
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句