为什么 Haskell 中不允许同时定义所有类型的函数? [英] Why is function definition for all types at once not allowed in Haskell?

查看:27
本文介绍了为什么 Haskell 中不允许同时定义所有类型的函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这可能是一个非常基本的问题,但是......

This is probably a very basic question, but ...

一个被定义为的函数,比如说

A function that's defined as, say

foo :: a -> Integer

表示从 any 类型到整数的函数.如果是这样,那么理论上应该能够为任何类型定义它,就像这样

denotes a function from any type to an Integer. If so, then in theory one should be able to define it for any type, like so

foo 1 = 10
foo 5.3 = 100
foo (x:xs) = -1
foo  _     = 0

但是 Haskell 只允许一个通用的定义,比如 foo a = 0.

But Haskell only allows a general definition, like foo a = 0.

即使你将 a 限制为某一类类型之一,例如 Show 类型类的一个实例:

And even if you restrict a to be one of a certain class of types, such as an instance of the Show typeclass :

foo :: (Show a) => a -> Integer

你仍然不能做这样的事情

you still can't do something like

foo "hello" = 10
foo   _     = 0

即使 "hello" :: [Char]Show

为什么会有这样的限制?

Why is there such a restriction?

推荐答案

这是一个功能,实际上是非常基础的.它归结为编程语言理论中称为参数化的属性.粗略地说,这意味着评估永远不应该依赖于编译时作为变量的类型.您不能静态地查看不知道其具体类型的值.

It's a feature, and actually is very fundamental. It boils down to a property known as parametricity in programming language theory. Roughly, that means that evaluation should never depend on types that are variables at compile time. You cannot look at a value where you do not know its concrete type statically.

为什么这么好?它为程序提供了更强的不变量.例如,您仅从类型就知道 a ->a 必须是恒等函数(或发散).类似的自由定理"适用于许多其他多态函数.参数化也是更高级的基于类型的抽象技术的基础.例如 Haskell 中的类型 ST sa(状态 monad),以及对应的 runST 函数的类型,依赖于 s 是参数化的.这确保了正在运行的函数不会干扰状态的内部表示.

Why is that good? It gives much stronger invariants about programs. For example, you know from the type alone that a -> a has to be the identity function (or diverges). Similar "free theorems" apply to many other polymorphic functions. Parametricity also is the basis for more advanced type-based abstraction techniques. For example, the type ST s a in Haskell (the state monad), and the type of the corresponding runST function, rely on s being parametric. That ensures that the running function has no way of messing with the internal representation of the state.

这对于有效实施也很重要.程序不必在运行时传递昂贵的类型信息(类型擦除),并且编译器可以为不同的类型选择重叠的表示形式.作为后者的一个例子,0和False以及()和[]在运行时都用0表示.如果允许使用像您这样的功能,这将是不可能的.

It is also important for efficient implementation. A program does not have to pass around costly type information at run time (type erasure), and the compiler can choose overlapping representations for different types. As an example of the latter, 0 and False and () and [] are all represented by 0 at runtime. This wouldn't be possible if a function like yours was allowed.

这篇关于为什么 Haskell 中不允许同时定义所有类型的函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆