Haskell 什么是=>;你的意思是什么?
我刚开始向您学习Haskell,我在一个示例中看到了这一点,没有解释:Haskell 什么是=>;你的意思是什么?,haskell,symbols,Haskell,Symbols,我刚开始向您学习Haskell,我在一个示例中看到了这一点,没有解释: tell :: (Show a) => [a] -> String 这意味着什么,尤其是=>?我知道如果我替换->或删除它,它将不起作用,但我真的不明白为什么。这是对类型的约束,意味着a应该是类Show的实例 请参见示例首先介绍并解释了=>: ==函数的类型签名是什么 ghci> :t (==) (==) :: (Eq a) => a -> a -> Bool 注意:相等运算符
tell :: (Show a) => [a] -> String
这意味着什么,尤其是
=>
?我知道如果我替换->
或删除它,它将不起作用,但我真的不明白为什么。这是对类型的约束,意味着a
应该是类Show
的实例
请参见示例首先介绍并解释了
=>
:
==函数的类型签名是什么
ghci> :t (==)
(==) :: (Eq a) => a -> a -> Bool
注意:相等运算符==是一个函数。所以是+、*、-、/和
几乎所有的运营商。如果函数仅由特殊
字符,默认情况下它被视为中缀函数。如果我们愿意
要检查其类型,请将其传递给另一个函数或作为
前缀函数,我们必须用括号括起来
有趣。我们在这里看到了一个新的东西,=>符号。以前的一切
=>符号称为类约束。我们可以阅读前面的文章
类型声明如下:相等函数接受任意两个值
属于相同类型并返回布尔值的。这两种类型
值必须是Eq类的成员(这是类
限制)
这是另一种看待它的方式。函数的某些参数是不可见的,其他参数是可见的。类型
input->output
告诉我们一个可见的input
应该作为参数。类型(约束)=>output
告诉我们需要一些不可见的信息。它们是不可互换的,因为可见的参数必须写,而不可见的参数不能写。这些看不见的论据需要编译器自己去理解(好吧,在我看来,他听起来像是一个独裁者),他坚持要把它们弄明白:他拒绝仅仅被告知它们是什么
秘密地,这个tell
示例的完整类型是
tell :: forall (a :: *). (Show a) => [a] -> String
我所做的是弄清楚这个变量是从哪里来的,它是什么类型的。您也可以将此理解为“交易”:tell
为满足需求的所有类型a
提供工作(Show a)
为了使tell
的用法有意义,它需要三件事。其中两个不可见,一个可见。也就是说,当您使用tell
时,您将visibile参数显式化,编译器将尝试填充不可见的部分。让我们慢慢地完成这类工作
tell :: forall (a :: *). -- the type of elements to tell (invisible)
(Show a) => -- how to make a String from one element (invisible)
[a] -> -- the list of elements to be told (visible)
String -- the String made by showing all the elements
因此,当您使用告诉,例如
tell [True, False]
您只给出可见的参数:列表[True,False]
中要说明的内容,编译器会计算出不可见的参数。他知道True
和False
都是Bool
类型的值,这意味着
[True, False] :: [Bool]
这就是编译器如何计算出tell
类型中的a
必须是Bool
,使[a]=[Bool]
(顺便说一句,关于[True,False]:[Bool]
。左边的:,方括号,[…],生成列表值。右边的:,方括号,[…],制作一类列表。它们可能在灰色背景下看起来是黑色的,但我的大脑将值标记括号染成红色,将类型标记括号染成蓝色。它们完全不同。我希望我能在这个网站上使用颜色代码。我离题了。)
所以,现在,另一个不可见的参数必须满足这个(Show a)
的要求,我们现在知道它具体是(Show Bool)
,因为我们发现a
是Bool
。我们称这部分类型为“约束”,但实际上这是一种要求,不仅要求事实是真实的,而且要求存在一些有用的东西。这里需要的是一个函数
show :: Bool -> String
该函数用于在计算tell[True,False]
的过程中将单个元素True
和False
转换为String
s
标识符Show
是类型类的名称,Show是该类型类的方法。类型类
指定必须为每个实例
实现的操作接口。该函数的不可见参数是一个记录(或“字典”),它打包了相关类型的这些操作的实现(这里是show
)的实现)。如果没有这些信息,编译后的代码将无法完成其工作,但我们不必编写这些信息,因为编译器可以(至少在本例中)搜索它所知道的实例,并为该工作填写正确的实例
因此,我们不仅仅有不可见的类型参数(在编译时推断,然后在运行时删除),由小写类型变量表示,或者更明确地说,由for all
blah
表示。我们还有类型类操作的不可见实现(在编译时查找,以提供重要的运行时信息)。因此,在推断和删除类型之间发生了一些非常重要的事情:虽然编译器仍然知道类型,但它使用它们来确定在运行时需要哪些不可见的实现,这样我们就可以不用自己编写它们了
缩小范围,=>
在类型文档中,我们期望编译器将利用类型信息来指导生成我们不必费心编写的运行时代码。这是一个不错的小胜利,就在那里
类型系统黑客的别有用心。不可见的可见区别与可擦除的有用区别位于不同位置的信息是一些人尚未收到的信息。这是辛德利·米尔纳的经典立场,但事实是,这些区别是正交的,人们越早学会享受这一点越好。你找到答案了吗