什么意思是(Haskell的)语义受到推断类型(返回类型多态性)的影响? [英] What does it mean that the semantics (of Haskell) are affected by the inferred types (of return type polymorphism)?

查看:163
本文介绍了什么意思是(Haskell的)语义受到推断类型(返回类型多态性)的影响?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

评论员在这里写下


最后,给定足够的宏魔法,这可以做到,但现在可能比Clojure上面实现一个Haskell风格的类型系统更少的努力。类型化Clojure可以是一个很好的模型,除非它被明确设计,使得Clojure的语义不会受到推断类型的影响。这正是在返回类型多态性中发生的,因此在类型化Clojure中显然是不可能的。

Finally, given enough macro magic this could be done... but likely for now less effort than implementing a Haskell-style type system atop Clojure. Typed Clojure could be a great model for this except it's been explicitly designed so that the semantics of Clojure cannot be affected by the inferred types. This is exactly what happens in return type polymorphism and so it's explicitly impossible in Typed Clojure.

我的问题是 - 这意味着Haskell的语义受到推断类型(返回类型多态性)的影响?

推荐答案

考虑具有(ad-hoc)多态返回值的 read 函数:

Consider the read function, which has an (ad-hoc) polymorphic return value:

read :: (Read a) => String -> a

实现不那么重要。唯一重要的部分是,实现取决于在编译时选择的 Read 的实例,并且推断可以导致为同一个调用选择不同的类型 read

The implementation isn't so important. The only important part is that the implementation depends on the instance of Read chosen at compile time, and that inference can result in different types being chosen for the same call to read.

addFive :: Int -> Int
addFive x = x + 5

main :: IO ()
main = do
    print (addFive (read "11"))
    putStrLn (read "11")

有一个 c $ c>两次使用相同的参数。 Haskell需要引用透明度,所以它必须导致同样的事情两次,对吧?嗯,不完全。推断的回报类型是重要的。在 print 行中,推断的返回类型为 Int 。在 putStrLn 行中,推断的返回类型为 String

There's a call to read with the same argument twice. Haskell requires referential transparency, so it has to result in the same thing both times, right? Well, not quite. The inferred return type matters. In the print line, the inferred return type is Int. In the putStrLn line, the inferred return type is String. And because it's ad-hoc polymorphic, the semantics change with with the type variable.

print 行会打印出来因为11不是的输入,所以 putStrLn

The print line will print out 16. The putStrLn line will crash, because "11" is not an input that read will successfully decode into a String.

因为类型变量只出现在在返回类型中,在调用函数时没有该类型的值。没有办法在运行时派遣一个值的类型来找出 Read 的使用实例。找出它的唯一方法是通过在编译时知道类型。

And because the type variable appears only in the return type, there's no value of that type at the time the function is called. There's no way to dispatch on a value's type at runtime to figure out what instance of Read to use. The only way to figure it out is by knowing the type at compile time. So Typed Clojure can't do this - it means semantics depend on compile-time types.

我不知道应该给你留下什么印象。但由于你的陈述(2)在任何可能的方式是错误的,它表明明显缺乏基础,甚至理解这个例子。我想我必须一路回到Haskell中的一个类型变量意味着来解释这一点。

I have no idea if it's supposed to impress you. But since your statement (2) is wrong in every way possible, it indicates a clear lack of foundations for even understanding this example. I think I have to go all the way back to what a type variable means in Haskell to explain this.

Haskell中的类型变量表示一个未知但具体的类型,由调用者选择。类型读取a =>字符串 - > a 并不意味着函数基于其输入为其返回值选择类型。

A type variable in Haskell represents an unknown but concrete type, chosen by the caller. The type Read a => String -> a does not mean the function chooses a type for its return value based on its input. It means that the function chooses how it will work based on the type it outputs.

也许读取是一个不好的示例,因为它的变化的行为看起来特别不同,当它由于错误的输入抛出异常。对于没有Haskell类型系统经验的人来说,很容易与类似运行时类型转换异常的东西混淆,即使它完全不同。

Perhaps read was a bad example, in that its varying behaviors only look particularly different when it throws an exception due to bad input. And it's really easy for people with no experience with Haskell's type system to conflate that with something like a runtime casting exception, even though it's entirely different.

您的语句(2)是完全错误的。程序不会崩溃,因为读取返回 Int 其中代码需要 String ,并且像 ClassCastException 会发生。程序崩溃,因为 read 选择了一个解析器来根据编译时的返回类型解析 String / strong>,但是给出的输入不是有效的 String 文本。 (相反,\11 \是有效的 String 文字,因为它被引用。

Your statement (2) is entirely wrong. The program does not crash because read returns an Int where the code expected a String, and something like a ClassCastException happens. The program crashes because read chose a parser for parsing String literals based on its return type at compile time, but the input it was given was not a valid String literal. (In contrast, "\"11\"" is a valid String literal because it is quoted.)

粗体部分是重要的部分。 read 函数根据返回类型选择在编译时使用的解析器。这是一个非常强大的技术,你不能用Typed Clojure。

The bolded part is the important part. The read function chooses what parser it's going to use at compile time based on the return type. That is both an extremely powerful technique, and something you cannot do with Typed Clojure.

这篇关于什么意思是(Haskell的)语义受到推断类型(返回类型多态性)的影响?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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