根据函数的类型确定函数的行为

发布于 2025-01-11 16:18:52 字数 713 浏览 0 评论 0原文

Haskell 新手,如果这是非常基本的,那么很抱歉

这个示例取自“真实世界 Haskell” -

ghci> :type fst  
fst :: (a, b) -> a

它们显示了 fst 函数的类型,然后遵循本段...

“结果类型fsta 我们已经提到参数多态性使得真实类型不可访问:fst 不会。没有足够的信息来构造类型的值a,也不能将 a 转换为 b< /strong> 因此,它唯一可能的有效行为(忽略无限循环或崩溃)是返回该对的第一个元素。”

我觉得我错过了该段落的基本要点,也许还有一些关于 Haskell 的重要内容。为什么 fst 函数不能返回类型 b?为什么它不能将元组作为参数,而只是返回一个 Int (或任何其他不是 a 的类型)?我不明白为什么它必须返回类型 a

谢谢

New to Haskell so sorry if this is very basic

This example is taken from "Real World Haskell" -

ghci> :type fst  
fst :: (a, b) -> a

They show the type of the fst function and then follow it with this paragraph...

"The result type of fst is a. We've already mentioned that parametric polymorphism makes the real type inaccessible: fst doesn't have enough information to construct a value of type a, nor can it turn an a into a b. So the only possible valid behaviour (omitting infinite loops or crashes) it can have is to return the first element of the pair."

I feel like I am missing the fundamental point of the paragraph, and perhaps something important about Haskell. Why couldn't the fst function return type b? Why couldn't it take the tuple as a param, but simply return an Int ( or any other type that is NOT a)? I don't understand why it MUST return type a?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

柠檬色的秋千 2025-01-18 16:18:52

如果它做了任何这些事情,它的类型就会改变。引用的意思是,鉴于我们知道 fst 的类型为 (a, b) -> a,我们可以对其进行这些推论。如果它有不同的类型,我们将无法这样做。

例如,看到

snd :: (a, b) -> a
snd (x, y) = y

不进行类型检查,因此我们知道 (a, b) -> 类型的值a 的行为不能像 snd 那样。

参数化基本上是这样一个事实:某种类型的多态函数必须通过构造遵守某些规则,即,不存在不遵守这些规则的该类型的良类型表达式。因此,为了能够用它来证明fst的事情,我们必须首先知道fst的类型。

特别注意这里的“多态性”这个词:我们不能对非多态类型进行同样的推论。例如,

myFst :: (Int, String) -> Int
myFst (a, b) = a

类型检查,但参数也是如此

myFst :: (Int, String) -> Int
myFst (a, b) = 42

,甚至

myFst :: (Int, String) -> Int
myFst (a, b) = length b

参数化都严重依赖于这样一个事实:多态函数无法“查看”调用它的类型。因此,fst 知道的唯一类型 a 值就是它所给出的值:元组的第一个元素。

If it did any of those things, its type would change. What the quote is saying is that, given that we know fst is of type (a, b) -> a, we can make those deductions about it. If it had a different type, we would not be able to do so.

For instance, see that

snd :: (a, b) -> a
snd (x, y) = y

does not type-check, and so we know a value of type (a, b) -> a cannot behave like snd.

Parametricity is basically the fact that a polymorphic function of a certain type must obey certain laws by construction — i.e., there is no well-typed expression of that type that does not obey them. So, for it to be possible to prove things about fst with it, we must first know fst's type.

Note especially the word polymorphism there: we can't do the same kind of deductions about non-polymorphic types. For instance,

myFst :: (Int, String) -> Int
myFst (a, b) = a

type-checks, but so does

myFst :: (Int, String) -> Int
myFst (a, b) = 42

and even

myFst :: (Int, String) -> Int
myFst (a, b) = length b

Parametricity relies crucially on the fact that a polymorphic function can't "look" at the types it is called with. So the only value of type a that fst knows about is the one it's given: the first element of the tuple.

筑梦 2025-01-18 16:18:52

关键是,一旦有了这种类型,实现选项就受到很大限制。如果您返回 Int,那么您的类型将为 (a,b) ->整数。由于a可以是任何东西,我们不能在实现中凭空产生一个而不诉诸undefined,因此必须返回由呼叫者。

The point is that once you have that type, the implementation options are greatly limited. If you returned an Int, then your type would be (a,b) -> Int. Since a could be anything, we can't gin one up out of thin air in the implementation without resorting to undefined, and so must return the one given to us by the caller.

凯凯我们等你回来 2025-01-18 16:18:52

您应该阅读免费定理文章。

You should read the Theorems for Free article.

贩梦商人 2025-01-18 16:18:52

让我们尝试在现实世界 Haskell 已经提供的基础上添加更多的挥手动作。让我们尝试说服自己,假设我们有一个类型为 (a,b) -> 的函数 fst 。 a 唯一可以是的总函数如下:

fst (x,y) = x

首先,我们不能返回除 a 类型的值以外的任何内容,前提是 fst 具有 a 类型代码>(a,b) -> a,所以我们不能有 fst (x,y) = yfst (x,y) = 1 因为它没有正确的类型。

现在,正如 RWH 所说,如果我给 fst 一个 (Int,Int)fst 不知道这些是 Int,此外,< code>a 或 b 不需要属于任何类型类,因此 fst 没有与 a 关联的可用值或函数或b

因此,fst 只知道我给它的 a 值和 b 值,并且无法转动 b > 到 a 中(它不能创建 b -> a 函数),因此它必须返回给定的 a 值。

这实际上不仅仅是神奇的挥手,人们实际上可以推断出给定多态类型有哪些可能的表达式。实际上有一个名为 djinn 的程序正是这样做的。

Let's try to add some more hand-waving to that already given by Real World Haskell. Lets try to convince ourselves that given that we have a function fst with type (a,b) -> a the only total function it can be is the following one:

fst (x,y) = x

First of all, we cannot return anything other then a value of type a, that is in the premise that fst has type (a,b) -> a, so we cannot have fst (x,y) = y or fst (x,y) = 1 because that does not have the correct type.

Now, as RWH says, if I give fst an (Int,Int), fst doesn't know these are Ints, furthermore, a or b are not required to belong to any type class so fst has no available values or functions associated with a or b.

So fst only knows about the a value and the b value that I give it and I can't turn b into an a (It can't make a b -> a function) so it must return the given a value.

This isn't actually just magical hand waving, one can actually deduce what possible expressions there are of a given polymorphic type. There is actually a program called djinn that does exactly that.

ˇ宁静的妩媚 2025-01-18 16:18:52

这里的要点是 ab 都是类型变量(可能相同,但这不是必需的)。无论如何,由于对于给定的两个元素元组,fst 始终返回第一个元素,因此返回的类型必须始终与第一个元素的类型相同。

The point here is that both a and b are type variables (that might be the same, but that's not needed). Anyway, since for a given tuple of two elements, fst returns always the first element, the returned type must be always the same as the type for the first element.

末が日狂欢 2025-01-18 16:18:52

您可能缺少的基本内容是:

  • 在大多数编程语言中,如果您说“此函数返回任何类型”,则意味着该函数可以决定它实际上的值类型

  • 在 Haskell 中,如果你说“这个函数返回任何类型”,这意味着调用者可以决定应该是什么类型。 (!)

所以如果我你写 foo :: Int -> x,它不能只返回一个String,因为我可能不会要求它提供一个String。我可能会要求提供CustomerThreadId任何东西

显然,foo 不可能知道如何创建每种可能类型的值,甚至是尚不存在的类型。简而言之,不可能写成foo。您尝试的所有操作都会出现类型错误,并且无法编译。

(警告:有一种方法可以做到这一点。foo可以永远循环,或者抛出异常。但是它不能返回有效值。 )

函数无法创建任何可能类型的值。但是函数完全有可能移动数据而不关心它是什么类型。因此,如果您看到一个接受任何类型数据的函数,它唯一能做的就是移动它。

或者,如果该类型必须属于特定类,则该函数可以在其上使用该类的方法。 (可以。它不必这样做,但如果它愿意的话可以。)

从根本上来说,这就是为什么你可以真正告诉函数的作用< /em> 只需查看其类型签名。类型签名告诉您函数“了解”将要提供的数据的哪些信息,以及它可能执行的操作。这就是为什么通过类型签名搜索 Haskell 函数非常有用。

你听说过“在 Haskell 中,如果它能编译,通常就能正常工作”这样的说法吗?嗯,这就是原因。 ;-)

The fundamental thing you're probably missing is this:

  • In most programming languages, if you say "this function returns any type", it means that the function can decide what type of value it actually returns.

  • In Haskell, if you say "this function returns any type", it means that the caller gets to decide what type that should be. (!)

So if I you write foo :: Int -> x, it can't just return a String, because I might not ask it for a String. I might ask for a Customer, or a ThreadId, or anything.

Obviously, there's no way that foo can know how to create a value of every possible type, even types that don't exist yet. In short, it is impossible to write foo. Everything you try will give you type errors, and won't compile.

(Caveat: There is a way to do it. foo could loop forever, or throw an exception. But it cannot return a valid value.)

There's no way for a function to be able to create values of any possible type. But it's perfectly possible for a function to move data around without caring what type it is. Therefore, if you see a function that accepts any kind of data, the only thing it can be doing with it is to move it around.

Alternatively, if the type has to belong to a specific class, then the function can use the methods of that class on it. (Could. It doesn't have to, but it can if it wants to.)

Fundamentally, this is why you can actually tell what a function does just by looking at its type signature. The type signature tells you what the function "knows" about the data it's going to be given, and hence what possible operations it might perform. This is why searching for a Haskell function by its type signature is so damned useful.

You've heard the expression "in Haskell, if it compiles, it usually works right"? Well, this is why. ;-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文