2

所以,基本上我有一些单子函数包装在MaybeT我想Nothing用作递归的终止案例

我的理解foldr是,如果它可以在不消耗整个列表的情况下产生结果,那么它可以安全地用于无限列表,即foldr (&&) True $ repeat False仍然能够返回False

目前我有:

repeaterM a f = foldr (=<<) (return a) $ repeat f

这种类型检查,但实际上不起作用。谁能向我解释为什么我不能使用这个函数重复地将一个函数应用于它自己的结果,直到它返回Nothing

4

1 回答 1

4
foldr            :: (a -> b -> b) -> b -> [a] -> b
foldr k z = go
          where
            go []     = z
            go (y:ys) = y `k` go ys

所以

foldr (&&) True $ repeat False
   = go (repeat False) where go [] = True ; go (y:ys) = y && go ys
   = False && go (repeat False) where go [] = True ; go (y:ys) = y && go ys
   = False

如你所料。

foldr (=<<) (return a) $ repeat f
   = go (repeat f) where go [] = return a ; go (y:ys) = y =<< ys
   = f =<< go (repeat f) where go [] = return a ; go (y:ys) = y =<< ys
   = f =<< f =<< go (repeat f) where go [] = return a ; go (y:ys) = y =<< ys
   = f =<< f =<< f =<< go (repeat f) where go [] = return a ; go (y:ys) = y =<< ys
   ...

您在这里所做的不是重复将函数应用于它自己的结果,直到它返回Nothing

您正在从头开始构建计算:=<<必须先计算每个的 RHS,然后才能执行 LHS。但是你有一个无限的列表,所以你永远不会开始计算。

您可以尝试定义

repeaterM a f = foldl (>>=) (return a) $ repeat f

反而。这也不起作用(感谢 is7s)。

于 2012-06-27T02:35:41.547 回答