Haskell Data.Stream的Monad实例的定义

Haskell Data.Stream的Monad实例的定义,haskell,monads,Haskell,Monads,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获取第

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发现,他证明了有理数和自然数一样多:

现在我的问题是,使用沿所有次对角线的路径(访问每个流的每个元素)进行的
连接是否也是有效的实现。或者这会违反单子定律吗

这会违反

return x >>= f === f x
考虑

f k = Cons k (f (k+1))
现在
fmap f(return 1)
repeat(f1)
,如果
join
遍历了所有元素,在生成的
流中,元素将重复

作为一个二维表,
fmap f(返回1)
如下所示

1 2 3 4 ...
1 2 3 4 ...
1 2 3 4 ...
如果你沿着第二条对角线穿过它,你会得到

1 1 2 1 2 3 1 2 3 4 ...

而不是
12345…
f1

我最近为列表monad实现了类似的功能:

diagonals :: [[(Integer, Integer)]]
diagonals =
    let diagonal index =
        do
            number <- [0..index]
            return (number, index - number)
    in map diagonal (enumFrom 0)

newtype Enumerable a = Enumerable { list :: [a] }

instance Monad Enumerable where
    return item = Enumerable [item]
    enumerable1 >>= getEnumerable2 =
        let
            list1 = list enumerable1
            diagonalItems diagonal =
                do
                    (index1, index2) <- diagonal
                    guard (containsIndex list1 index1)
                    let item1 = genericIndex list1 index1
                    let list2 = list (getEnumerable2 item1)
                    guard (containsIndex list2 index2)
                    let item2 = genericIndex list2 index2
                    return item2
        in Enumerable (concat (takeWhile (not . null) (map diagonalItems diagonals)))
为您提供一个无限列表,其中包含第二项大于或等于1、第三项大于或等于2的所有自然数三元组

我检查了一下,如果我没有犯错误,它应该遵守所有的单子定律。它也适用于有限列表,在遇到完全为空的对角线后,它将停止尝试查找新项目

我不熟悉stream monad,所以我也无法告诉您如果您在那里做了类似的事情会发生什么。

对于
stream
,只有一个(合理的)monad,但是有很多comonad。详见布伦特系列。
list
(
    do
        item1 <- Enumerable [0..]
        item2 <- Enumerable [1..]
        item3 <- Enumerable [2..]
        return (item1, item2, item3)
)