Data.Stream的monad instanc以这样的方式定义:
instance Monad Stream where
return = repeat
xs >>= f = join (fmap f xs)
where
join :: Stream (Stream a) -> Stream a
join ~(Cons xs xss) = Cons (head xs) (join (map tail xss))
这意味着join
获取第一个流的第一个元素,第二个流的第二个元素等,因此生成的流可以被视为“主对角线”,丢弃所有其他元素。
现在有一种方法可以通过一个无限的二维表格,由Georg Cantor发现,因为他证明了有多少有理数和自然数:http://www.jcu.edu/math/vignettes/infinity.htm
现在我的问题是,join
使用沿所有辅助对角线的路径(访问每个流的每个元素)是否也是有效的实现。或者这会违反monad法律之一吗?
答案 0 :(得分:9)
会违反
return x >>= f === f x
考虑
f k = Cons k (f (k+1))
现在fmap f (return 1)
为repeat (f 1)
,如果join
通过了所有元素,则生成的Stream
元素会重复。
作为二维表,fmap f (return 1)
看起来像
1 2 3 4 ...
1 2 3 4 ...
1 2 3 4 ...
如果你在次要对角线之后遍历那个,你得到
1 1 2 1 2 3 1 2 3 4 ...
而不是1 2 3 4 5 ...
与f 1
一样。