将作为参数传递的函数应用于Haskell中的不同类型

将作为参数传递的函数应用于Haskell中的不同类型,haskell,parametric-polymorphism,Haskell,Parametric Polymorphism,有没有办法将作为参数传递的函数应用于两种不同的类型?作为一个精心设计的示例,我可以使用表达式(仅3,仅为True)创建一个(可能是Int,可能是Bool),但如果我尝试使此行为更通用于函数 generic :: (a -> Maybe a) -> (Maybe Int, Maybe Bool) generic f = (f 3, f True) 因此,我可能会执行类似于generic Just,编译器会抱怨,因为类型变量a是常量 该用例是将通用函数应用于树结构,其中每个节点由一个类

有没有办法将作为参数传递的函数应用于两种不同的类型?作为一个精心设计的示例,我可以使用表达式
(仅3,仅为True)
创建一个
(可能是Int,可能是Bool)
,但如果我尝试使此行为更通用于函数

generic :: (a -> Maybe a) -> (Maybe Int, Maybe Bool)
generic f = (f 3, f True)
因此,我可能会执行类似于
generic Just
,编译器会抱怨,因为类型变量
a
是常量


该用例是将通用函数应用于树结构,其中每个节点由一个类型参数化。

这可以通过使用秩-2多态性实现,如下所示:

{-# LANGUAGE Rank2Types #-}
generic :: (forall a. a -> Maybe a) -> (Maybe Int, Maybe Bool)
generic f = (f 3, f True)
通常,您需要一些类型类限制(不是因为
generic
的实现需要它,而是因为调用者无法传递适用于所有类型的参数),例如


我不知道您对此有何感想,但当我使用一个为所有启用
的扩展时,我总是打开
ScopedTypeVariables
;否则,我很可能会迷路。太好了,谢谢!你知道有什么好的资源可以通过这些现代语言扩展来使用吗?我能找到的所有Haskell书籍大多都是关于Haskell 98的,Haskell文档可能会非常累人……@igorbark如果你想要所有的扩展,没有比这更好的来源了。@igorbark:似乎有一些人已经使用了它。
genericNum :: (forall a. Num a => a -> a) -> (Int, Integer)
genericNum f = (f 3, f 9)