简而言之:一种是种什么类型就是值.
什么是价值?1,2,3是价值观.那么,"Hello"和"World",true和false,等等.
值属于类型.类型描述一组值.1,2并且3属于类型Nat,"Hello"并且"World"该类型Text,true并且false该类型Boolean.
函数将一个或多个值作为参数,并生成一个或多个值作为结果.为了有意义地对参数做一些事情,函数需要对它们做一些假设,这是通过约束它们的类型来完成的.因此,函数参数和返回值通常也有类型.
现在,函数也有一个类型,由其输入和输出的类型描述.例如,abs计算数字绝对值的函数具有类型
Number -> NonNegativeNumber
Run Code Online (Sandbox Code Playgroud)
add添加两个数字的功能具有类型
(Number, Number) -> Number
Run Code Online (Sandbox Code Playgroud)
该函数divmod具有类型
(Number, Number) -> (Number, Number)
Run Code Online (Sandbox Code Playgroud)
好的,但是如果函数将值作为参数并将值作为结果生成,并且函数是值,那么函数也可以将函数作为参数并将函数作为结果返回,对吧?这种功能的类型是什么?
假设我们有一个函数findCrossing可以找到一些其他函数(数字)与y轴相交的点.它将函数作为参数并作为结果产生一个数字:
(Number -> Number) -> Number
Run Code Online (Sandbox Code Playgroud)
或者是一个函数makeAdder,它产生一个函数,它接受一个数字并为其添加一个特定的数字:
Number -> (Number -> Number)
Run Code Online (Sandbox Code Playgroud)
并且计算另一个函数的导数的函数:
(Number -> Number) -> (Number -> Number)
Run Code Online (Sandbox Code Playgroud)
让我们看一下这里的抽象层次:价值是非常具体的.这只意味着一件事.如果我们在这里订购我们的抽象级别,我们可以说一个值的顺序为0.
一个函数,OTOH更抽象:单个函数可以产生许多不同的值.所以,它有订单1.
返回或接受函数的函数更加抽象:它可以产生许多不同的函数,这些函数可以产生许多不同的值.它有订单2.
通常,我们使用> 1" 更高阶 " 的订单调用所有内容.
好的,但那种呢?好了,我们上面提到1,2,"Hello",false等有型.但是什么类型的Number?还是Text?还是Boolean?
嗯,它的类型Type当然是!这种"类型的类型"被称为一种.
就像我们可以拥有从值构造值的函数一样,我们可以使用从类型构造类型的函数.这些函数称为类型构造函数.
就像函数有类型一样,类型构造函数也有类型.例如,List类型构造函数采用元素类型并为该元素生成列表类型
Type -> Type
Run Code Online (Sandbox Code Playgroud)
该Map类型的构造,需要一个密钥类型和值类型,并产生一个地图类型具有类
(Type, Type) -> Type
Run Code Online (Sandbox Code Playgroud)
现在,继续类比,如果我们可以使用函数作为参数,我们还可以使用类型构造函数将类型构造函数作为参数吗?当然!
一个例子是Functor类型构造函数.它需要一个类型构造函数并生成一个类型:
(Type -> Type) -> Type
Run Code Online (Sandbox Code Playgroud)
请注意我们总是写Type在这里?上面,我们有很多不同的类型,如Number,Text,Boolean等在这里,我们永远都只有一种类型,即Type.这对于(警告,前面的不良双关语)类型来说是乏味的,所以Type我们只是写作而不是到处写*.即Functor有那种
(* -> *) -> *
Run Code Online (Sandbox Code Playgroud)
并且Number有那种
*
Run Code Online (Sandbox Code Playgroud)
继续类比,Number,Text和类型的所有其他*有秩序0,List和类型的所有其他人* -> *或者更一般(*, …) -> (*, …)有1阶,Functor并且所有的样(* -> *) -> *或* -> (* -> *)(等等)有秩序2.除在这种情况下,我们有时也把它叫做排名而不是订单.
超过顺序/等级1的所有内容称为高阶,高阶或更高阶.
我希望这个比喻现在很明确:类型描述了价值观; 种类描述了各种类型.
旁白:我完全忽略了currying.基本上,currying意味着你可以将任何带有两个值的函数转换为一个函数,该函数接受一个值并返回一个取另一个值的函数,类似于三个,四个,五个......参数.这意味着您只需要使用一个参数来处理函数,这使得语言更加简单.
然而,这也意味着从技术上讲,它add是一个高阶函数(因为它返回一个函数),这使得定义变得混乱.
The most eloquent explanation for kinds/higher-kinds I've seen so far and also in the context of Scala is Daniel Spiewak's High Wizardry in the Land of Scala. There are many versions, he gave this talk a few times, here I've chosen the longest one, but you can quickly google and find others.
本次演讲中最重要的信息正是@Jörg W Mittag 给出的答案:
“种类之于类型就像类型之于价值”
关于该主题的更理论观点的另一个地方是论文Generics of a Higher Kind,也在 Scala 的上下文中。