我刚刚开始了解你一个Haskell ,我在一个例子中看到了这个,没有解释:
tell :: (Show a) => [a] -> String
这是什么意思,特别是=>
?我知道如果我替换->
或删除它,它将无效。但我不明白为什么。
答案 0 :(得分:22)
这是另一种看待它的方式。某些函数的参数是不可见的,其他参数是可见的。类型input -> output
告诉我们预期可见input
作为参数。类型(Constraint) => output
告诉我们预期会有一些不可见的信息。它们不可互换,因为必须写入可见的参数,并且不能写入不可见的参数。隐形的论据是让编译器为自己弄清楚的(好吧,他听起来像是对我而言),他坚持要把它们搞得一团糟:他拒绝被告知它们是什么!
秘密地说,这个tell
示例的完整类型是
tell :: forall (a :: *). (Show a) => [a] -> String
我所做的是明确这个a
变量的来源以及它是什么样的东西。您还可以将此视为“交易”: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
时,例如,
tell [True, False]
你只给出了可见的参数:列出[True, False]
的东西,并且编译器会找出不可见的参数。他知道True
和False
都是Bool
类型的值,所以这意味着
[True, False] :: [Bool]
编译器如何确定a
类型中的tell
必须为Bool
,使[a] = [Bool]
(顺便说一下,约[True, False] :: [Bool]
。左边的::方括号,[..],列表值。右边的::方括号,[..],做一个类型它们可能只是在灰色的背景上看起来是黑色的,但是我的大脑将制作颜色的颜色设置为红色,而制作颜色的颜色为蓝色。它们完全不同。我希望我能在此网站上设置颜色代码。我离题了。)
所以,现在,另一个不可见的参数必须满足这个(Show a)
的东西,我们现在知道这是(Show Bool)
,因为我们发现a
是Bool
。我们将这部分类型称为“约束”,但实际上它不仅要求事实是真的,而且存在一些有用的东西。这里要求的东西是有一个功能
show :: Bool -> String
这是用于在评估True
的过程中将单个元素False
和String
转换为tell [True, False]
的函数。
标识符Show
是类型类的名称, show 是该类型类的方法。类型class
指定必须为每个instance
实现的操作接口。函数的不可见参数是一个记录(或“字典”)打包所讨论类型的操作的实现(这里是show
的实现)。如果没有这些信息,编译后的代码将无法完成其工作,但我们不必编写该信息,因为编译器可以(至少在这种情况下)搜索它知道的实例并填写右侧一个人的工作。
因此,我们不只是有不可见的类型参数(在编译时推断,然后在运行时删除),由小写类型变量发出信号,或者更明确地由forall
blah .
。我们还有类型类操作的不可见实现(在编译时查找,以提供重要的运行时信息)。因此,在推断和擦除类型之间发生了一些非常重要的事情:虽然编译器仍然知道类型,但它使用它们来确定在运行时需要哪些不可见的实现,这样我们就可以逃脱不是自己写的。
缩小,=>
在类型文档中我们期望编译器将使用类型信息来指导生成我们不必费心的运行时代码。那是一个很好的一点胜利,就在那里。
类型系统黑客的别有用心。无形 - 可见区别与可擦除有用区别不同的信息是某些人尚未收到的信息。这是典型的Hindley-Milner职位,但事实是这些区别是正交的,人们越早学会享受,就越好。
答案 1 :(得分:7)
=>
首先在Chapter 3 - Types and Typeclasses中介绍并解释:
==函数的类型签名是什么?
ghci> :t (==) (==) :: (Eq a) => a -> a -> Bool
注意:等于运算符,==是一个函数。 +,*, - ,/和 几乎所有运营商。如果函数仅包含特殊功能 字符,默认情况下被视为中缀函数。如果我们想要 检查其类型,将其传递给另一个函数或将其称为 前缀函数,我们必须用括号括起来。
有趣。我们在这里看到一个新的东西,=>符号。以前的一切 =>符号称为类约束。我们可以阅读以前的内容 这样的类型声明:相等函数接受任意两个值 具有相同类型并返回Bool。那两个的类型 values必须是Eq类的成员(这是类 约束)。
答案 2 :(得分:6)
它是对类型的约束,意味着string1.replaceAll("\\s","").equals(string2.replaceAll("\\s",""));
应该是类a
的实例。
请参阅示例here