aoc*_*via 5 polymorphism haskell parametric-polymorphism
在关于函数式编程的讲座中,我们看到了以下Haskell函数:
f :: Bool -> Int -> (a -> Int) -> Int
f x y z = if x then y + y else (z x) + (z y)
Run Code Online (Sandbox Code Playgroud)
预计此功能将无法进行类型检查.但是,没有解释这种情况发生的原因.在GHCI中尝试时,我得到以下输出:
Prelude> :l test [1 of 1] Compiling Main ( test.hs,
interpreted )
test.hs:2:35:
Couldn't match expected type `a' with actual type `Bool'
`a' is a rigid type variable bound by
the type signature for f :: Bool -> Int -> (a -> Int) -> Int
at test.hs:1:6
Relevant bindings include
z :: a -> Int (bound at test.hs:2:7)
f :: Bool -> Int -> (a -> Int) -> Int (bound at test.hs:2:1)
In the first argument of `z', namely `x'
In the first argument of `(+)', namely `(z x)' Failed, modules loaded: none.
为什么会这样?
f :: Bool -> Int -> (a -> Int) -> Int
f x y z = if x then y + y else (z x) + (z y)
Run Code Online (Sandbox Code Playgroud)
类型签名断言我们的函数z在其第一个参数中是多态的.它需要任何类型的值a并返回一个Int.但是,类型变量的范围a也意味着它a在所有用途中必须是相同的类型.a无法在同一个使用站点实例化为不同类型.这是"等级1多态性".
您可以真正阅读该类型:
f :: forall a. Bool -> Int -> (a -> Int) -> Int
Run Code Online (Sandbox Code Playgroud)
所以:
z (x :: Bool) + z (y :: Int)
Run Code Online (Sandbox Code Playgroud)
是无效的,因为它a被限制为两种不同的独立类型.
语言扩展允许我们更改范围,a以便可以将其实例化为多态变量 - 即在同一个使用站点保存不同类型,包括具有多态函数类型:
Prelude> :set -XRankNTypes
Prelude> let f :: Bool -> Int -> (forall a . a -> Int) -> Int
f x y z = if x then y + y else (z x) + (z y)
Run Code Online (Sandbox Code Playgroud)
现在该类型a没有全局范围,并且各个实例可以变化.这让我们编写"更多态"功能f并使用它:
Prelude> f True 7 (const 1)
14
Run Code Online (Sandbox Code Playgroud)
这就是更高等级的多态性是多么酷.更多代码重用.
| 归档时间: |
|
| 查看次数: |
330 次 |
| 最近记录: |