我正在讨论多态性,并试图了解这一特性的实际用途。
我对排名2的基本理解是:
type MyType = ∀ a. a -> a
subFunction :: a -> a
subFunction el = el
mainFunction :: MyType -> Int
mainFunction func = func 3我知道这允许用户在mainFunction中使用多态函数(MainFunction),并严格指定它的输出(Int)。这似乎与GADT的非常相似:
data Example a where
ExampleInt :: Int -> Example Int
ExampleBool :: Bool -> Example Bool( 1)鉴于以上所述,我对等级2多态性的理解是否正确?
2)例如,与GADT相比,可以使用等级2多态性的一般情况是什么?
发布于 2017-01-10 00:22:06
如果将多态函数as和参数传递给Rank2--多态函数,则实际上传递的不仅仅是一个函数,而是所有满足约束的可能类型的整个函数族。
通常,所有量词都带有类约束。例如,我可能希望同时进行两种不同类型的数字运算(用于比较精度或其他什么)。
data FloatCompare = FloatCompare {
singlePrecision :: Float
, doublePrecision :: Double
}现在,我可能需要通过一些数学操作来修改这些数字。有点像
modifyFloat :: (Num -> Num) -> FloatCompare -> FloatCompare但是Num不是一个类型,而是一个类型类。当然,我可以传递一个函数来修改任何特定的数字类型,但是我不能使用它来同时修改Float和Double值,至少在没有一些丑陋的(可能是有损耗的)来回转换的情况下是不可能的。
解决方案:秩-2多态性!
modifyFloat :: (∀ n . Num n => n -> n) -> FloatCompare -> FloatCompare
mofidyFloat f (FloatCompare single double)
= FloatCompare (f single) (f double)这在实践中是有用的最好的一个例子可能是镜片。镜头是对某个较大数据结构中的字段的“智能访问器函数”。它允许你访问字段,更新它们,收集结果.同时以一种非常简单的方式作曲。它的工作原理:Rank2-多态性;每个透镜都是多态的,不同的实例化分别对应于“getter”/“setter”方面。
发布于 2021-04-08 07:07:14
如果您在Haskell中使用模块,那么您已经在使用级别-2类型.从理论上讲,模是具有秩-2型性质的记录.
例如,下面的Haskell中的Foo模块..。
module Foo(id) where
id :: forall a. a -> a
id x = ximport qualified Foo
main = do
putStrLn (Foo.id "hello")
return ()..。实际上可以将其视为记录如下:
type FooType = FooType {
id :: forall a. a -> a
}
Foo :: FooType
Foo = Foo {
id = \x -> x
}P/S (不相关的这个问题):从语言设计的角度来看,如果您要支持模块系统,那么您最好支持更高级别的类型(即允许任意量化任何级别的类型变量),以减少重复工作(即类型检查模块应该与具有较高级别类型的记录类型检查几乎相同)。
https://stackoverflow.com/questions/41557954
复制相似问题