Mar*_*len 4 haskell types variable-assignment typeclass parametric-polymorphism
对Haskell来说是非常新的知识,它试图了解类型类和变量如何交互。
我要玩的第一件事是:
i :: a; i = 1
Run Code Online (Sandbox Code Playgroud)
我的期望是,由于我输入的字词尽可能通用,因此我应该绝对可以为其分配任何内容。(我知道我可能无法对变量i做任何事情,但这并不重要。)
但是我错了。上面给出了一个错误,并要求它是:
i :: Num a => a; i = 1
Run Code Online (Sandbox Code Playgroud)
经过多玩之后,我想到了以下内容:
g :: Num a => a -> a; g a = a + 1
g 1
(returned 2)
gg :: Num a => a; gg = g 1
gg
(returned 2)
Run Code Online (Sandbox Code Playgroud)
好的...到目前为止很好。让我们尝试一个小数参数。
g :: Num a => a -> a; g a = a + 1
g 1.3
(returned 2.3)
gg :: Num a => a; gg = g 1.3
(error)
Run Code Online (Sandbox Code Playgroud)
那么,请...导致变量的原因是什么?从非函数式编程背景来看,它“看起来”像我有一个函数,该函数返回实现Num的类型的值,并尝试将其分配给实现Num的类型的变量。但是,分配失败。
我确信这是我的一些基本误解。可能是同一件事使第一个示例无法正常工作。我真的很想弄清楚它,然后再开始犯更严重的概念错误。
Run Code Online (Sandbox Code Playgroud)i :: a; i = 1我的期望是,由于我输入的字词尽可能通用,因此我应该绝对可以为其分配任何内容。(我知道我可能无法对变量i做任何事情,但这并不重要。)
不,这是另一回事。该类型表示以后可以使用该值的方式,即表示用户可以i假装该值当时可能是任何类型。本质上,用户选择实际的类型a,并且代码定义i :: a必须符合用户的任何此类选择。
(通过我们通常所说的i = 1“绑定”或“定义”,而不是“分配”的方式,因为这意味着我们以后可以重新分配。)
Run Code Online (Sandbox Code Playgroud)gg :: Num a => a; gg = g 1.3 (error)
同样的原则在这里适用。gg声称是用户可能想要的任何数字类型,但是如果用户稍后选择,Int则定义g 1.3不适合Int。
用户可以使用显式签名(print (gg :: Int))选择类型,也可以将其置于“强制”该类型的上下文中(自返回以来print (length "hello" + gg)强制)。IntlengthInt
如果您熟悉其他一些语言中的“泛型”,则可以使用以下代码进行比较:
-- Haskell
i :: a
i = 1 -- type error
-- pseudo-Java
<A> A getI() {
return 1; -- type error
}
Run Code Online (Sandbox Code Playgroud)
从更理论的角度来看,您正在考虑错误的量词。当您编写时i :: a,您正在考虑i :: exists a . a(不是真正的Haskell类型)读为“ i是某种类型的值(在定义时选择)”。相反,在Haskell中,其i :: a含义i :: forall a . a为“ i是所有类型的值(使用时可能需要的任何类型)”。因此,归结为“存在”与“全部”,或“谁选择实际的类型类型a”。
| 归档时间: |
|
| 查看次数: |
98 次 |
| 最近记录: |