有没有办法将作为参数传递的函数应用于两种不同的类型?作为一个人为的例子,我可以使用表达式(Maybe Int, Maybe Bool)
创建一个(Just 3, Just True)
,但如果我尝试使用该函数使这种行为更通用
generic :: (a -> Maybe a) -> (Maybe Int, Maybe Bool)
generic f = (f 3, f True)
这样我可能会做generic Just
之类的事情,编译器会抱怨,因为类型变量a
是常量。
这个用例是将一个泛型函数应用于树结构,其中每个节点都按类型进行参数化。
答案 0 :(得分:9)
这可以使用如下的rank-2多态性来实现:
{-# LANGUAGE Rank2Types #-}
generic :: (forall a. a -> Maybe a) -> (Maybe Int, Maybe Bool)
generic f = (f 3, f True)
通常你需要一些类型类限制(不是因为generic
的实现要求它,而是因为调用者无法传递适用于所有类型的参数),例如。
genericNum :: (forall a. Num a => a -> a) -> (Int, Integer)
genericNum f = (f 3, f 9)