2016-02-05 27 views
4

有什么办法可以将函数作为参数传递给两种不同的类型吗?作为一个人为的例子,我可以创造与表达(Just 3, Just True)一个(Maybe Int, Maybe Bool),但如果我试图让这种行为更通用与功能应用函数作为参数传递给Haskell中的不同类型

generic :: (a -> Maybe a) -> (Maybe Int, Maybe Bool) 
generic f = (f 3, f True) 

,这样我也许能像做generic Just,编译器会抱怨因为类型变量a是不变的。

此用例将通用函数应用于每个节点通过类型进行参数化的树结构。

回答

9

这可以使用等级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) 
+1

我不知道你对此有什么看法,但我*总是*打开'ScopedTypeVariables'当我使用一个扩展,使'forall';否则我很可能会在路上感到困惑。 – dfeuer

+0

完美,非常感谢!你知道所有这些现代语言扩展的优秀资源吗?我所能找到的所有Haskell书籍大部分都与Haskell 98和Haskell文档相关,它们可能会让你非常疲惫...... – igorbark

+0

@igorbark如果你想要所有的扩展,没有比[马的嘴巴]更好的源代码(https:// downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghc-language-features.html)。 –

相关问题