在Haskell中使用Rank2多态函数遇到类型标注问题
Haskell中
inTransform函数的正确类型标注问题 你想要实现的函数:
inTransform tr f = tr . f . tr
你之前的错误原因
你尝试的Rank2类型标注:
inTransform :: (forall a. a -> a) -> (b -> c) -> (b -> c)
要求tr必须是能处理所有类型的多态函数(比如id),但reverse这类函数只能处理特定类型(这里是列表类型),无法满足forall a. a -> a的约束,因此编译器报错,提示reverse的类型[a0] -> [a0]无法匹配forall a1. a1 -> a1。
正确的类型标注方案
你需要的是让tr成为能处理某类类型的多态函数(比如所有列表类型),而非所有类型。正确的Rank2类型标注应该参数化一个类型构造器,让tr能处理该构造器下的任意类型:
inTransform :: (forall a. t a -> t a) -> (t b -> t c) -> (t b -> t c)
这里t是类型构造器(比如[]、Maybe),tr的类型forall a. t a -> t a表示它能接受任意t a类型并返回同类型结果,刚好匹配reverse这类针对容器的多态函数(reverse的类型是forall a. [a] -> [a],对应t = [])。
如果你只需要处理列表场景,也可以写更具体的类型:
inTransform :: (forall a. [a] -> [a]) -> ([b] -> [c]) -> ([b] -> [c])
验证你的示例
- 调用
inTransform reverse id [1, 6]:reverse符合forall a. [a] -> [a],id是[Int] -> [Int],函数执行逻辑为reverse (id (reverse [1,6])),最终返回[1,6],类型完全匹配。 - 调用
inTransform reverse (:[]) [1, 6]:(:[])的类型是[Int] -> [[Int]],符合[b] -> [c](b=Int,c=[Int]),函数执行逻辑为reverse ((:[]) (reverse [1,6])),最终返回[[6,1]],类型正确无报错。
关于其他建议类型的问题
有人建议的inTransform :: (a -> b) -> (b -> a) -> a -> b,要求f的类型是b -> a,但你的场景中f(比如(:[]))的输入输出类型并不互逆,因此这个类型无法满足你的需求。
内容的提问来源于stack exchange,提问作者louis
相关产品推荐
相关产品推荐

