概括可能和haskell中的任何一个函数

ill*_*out 4 generics haskell

haskell中是否有一个函数可以推广可能和任何一个函数?

例如,我想象一个这样的函数:

generalizedFunc :: SOMETHING m => b -> (a -> b) -> m a -> b
generalizedFunc valForError f value = ...
Run Code Online (Sandbox Code Playgroud)

在ghci中使用它看起来像这样:

> generalizedFunc "bye" (\_ -> "hello") (Just 3)
"hello"
> generalizedFunc "bye" (\_ -> "hello") Nothing
"bye"
> generalizedFunc "bye" (\_ -> "hello") (Right 3)
"hello"
> generalizedFunc "bye" (\_ -> "hello") (Left "error")
"bye"
Run Code Online (Sandbox Code Playgroud)

注意:Tom Ellis指出这不是Either的概括,而是专业化.

小智 5

是.你在寻找什么Data.Foldable.它将foldr(列表)推广到任何代数数据类型:

Data.List.foldr     :: (a -> b -> b) -> b     ->   []       a -> b
maybe               :: b -> (a -> b)          ->   Maybe    a -> b
either              :: (a -> c) -> (b -> c)   ->   Either a b -> c
---
Data.Foldable.foldr :: Foldable t
                    => (a -> b -> b) -> b     ->   t        a -> b
Run Code Online (Sandbox Code Playgroud)

您的代码将从更改generalizedFunc "bye" (\_ -> "hello")foldr (\_ _ -> "hello") "bye".确保告诉编译器你的意思是foldr来自Data.Foldable; 请参阅该模块的文档.

不幸的是,Foldable (Either a)您的GHC版本可能缺少实例,但自己编写一个应该相对容易.

  • `Data.Foldable`实际上只提供了从其他数据类型到`[]`的映射.[`Data.Functor.Foldable`](http://hackage.haskell.org/package/recursion-schemes-4.0/docs/Data-Functor-Foldable.html)提供了`foldr`的真正概括,命名为`cata `. (3认同)
  • @Carl:是的,在某种程度上.`foldMap`是一种更好的思考方式.但是对于大多数应用程序来说,`Data.Foldable`(或`Data.Traversable`)就足够了.抱怨"你不应该成为使用Haskell的类别理论专家",直接*指的是`Data.Functor.Foldable`; 它*看起来像一个非常繁琐的库,使用,由于缺乏适当的文档而变得更糟. (2认同)