Data.List 定义
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
unfoldr f b = case f b of
  Just (a,new_b) -> a : unfoldr f new_b
  Nothing -> []
有许多功能几乎可以使用unfoldr,但在列表的最后有问题.一个简单的"修复"是
unfoldr' :: (b -> Either (a,b) [a]) -> b -> [a]
unfoldr' f b = case f b of
  Left (a, new_b) -> a : unfoldr' f new_b
  Right r         -> r
这个功能有标准名称吗?它有不错的属性和良好的互动foldr吗?
(这更多是一条注释,带有一些代码,因此不适合)考虑您在注释中提到的测试用例,
f xs -- = zip (map reverse $ inits xs) (tails xs)
  = unfoldr g (Just ([],xs))
      where
        g (Just (acc,xs@[]))    = Just ( (acc,xs), Nothing)
        g (Just (acc,xs@(x:t))) = Just ( (acc,xs), Just (x:acc, t) )
        g Nothing = Nothing
感知到的问题是结束列表的一个额外处理节拍,这迫使我们使用嵌套的Maybe. 事实上,您的函数更容易(不需要嵌套Maybe):
  = unfoldr' h ([],xs)
      where
        h (acc,xs@[])    = Right [ (acc,xs) ]    -- last tail
        h (acc,xs@(x:t)) = Left  ( (acc,xs), (x:acc,t) )
但我们还可以g通过另一种方式简化代码:
  = unfoldr (fmap g') (Just ([],xs))
      where
        g' (acc,xs@[])    = ( (acc,xs), Nothing)   -- last element
        g' (acc,xs@(x:t)) = ( (acc,xs), Just (x:acc, t) )
并使用它作为此类功能的骨架,标准unfoldr仍然如此。Nothing或者也许定义中多一行代码g,那么,没有什么可担心的。
但是,如果您确实需要在列表中添加一个特殊的尾部,而不仅仅是一个元素,那么它当然无法替代。