我正在覆盖多态性,我试图看到这种功能的实际用途.
我对Rank 2的基本了解是:
type MyType = ? a. a -> a subFunction :: a -> a subFunction el = el mainFunction :: MyType -> Int mainFunction func = func 3
我知道这允许用户在mainFunction中使用多态函数(subFunction)并严格指定它的输出(Int).这似乎与GADT非常相似:
data Example a where ExampleInt :: Int -> Example Int ExampleBool :: Bool -> Example Bool
1)鉴于以上情况,我对Rank 2多态性的理解是否正确?
2)与GADT相比,可以使用Rank 2多态性的一般情况是什么?
如果将多态函数作为参数传递给Rank2多态函数,那么实际上您不仅要传递一个函数,而且传递整个函数族 - 对于满足约束的所有可能类型.
通常,这些forall量词具有类约束.例如,我可能希望同时使用两种不同的类型进行数字运算(用于比较精度或其他).
data FloatCompare = FloatCompare { singlePrecision :: Float , doublePrecision :: Double }
现在我可能想通过一些数学运算来修改这些数字.就像是
modifyFloat :: (Num -> Num) -> FloatCompare -> FloatCompare
但Num
不是类型,只是类型类.当然,我可以通过将修改任何一个功能特定号码类型,但我不能用它来修改既一个Float
和Double
值,至少在没有一些难看(以及可能有损)来回转换.
解决方案:Rank-2多态性!
modifyFloat :: (? n . Num n => n -> n) -> FloatCompare -> FloatCompare mofidyFloat f (FloatCompare single double) = FloatCompare (f single) (f double)
这在实践中如何有用的最好的单一例子可能是镜头.镜头是某些较大数据结构中的字段的"智能访问器功能".它允许您访问字段,更新它们,收集结果......同时以非常简单的方式编写.工作原理:Rank2-polymorphism; 每个镜头都是多态的,不同的实例分别对应于"getter"/"setter"方面.