“正义"是什么意思?Haskell 中的语法是什么意思? [英] What does the "Just" syntax mean in Haskell?

查看:49
本文介绍了“正义"是什么意思?Haskell 中的语法是什么意思?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经在互联网上搜索了有关此关键字作用的实际解释.我看过的每个 Haskell 教程只是随机开始使用它,从不解释它的作用(我看过很多).

I have scoured the internet for an actual explanation of what this keyword does. Every Haskell tutorial that I have looked at just starts using it randomly and never explains what it does (and I've looked at many).

这是来自Real World Haskell 的一段基本代码,它使用了Just.我明白代码的作用,但我不明白Just 的目的或功能是什么.

Here's a basic piece of code from Real World Haskell that uses Just. I understand what the code does, but I don't understand what the purpose or function of Just is.

lend amount balance = let reserve    = 100
                      newBalance = balance - amount
                  in if balance < reserve
                     then Nothing
                     else Just newBalance

据我观察,这与 Maybe 打字有关,但这几乎是我设法学习的全部内容.

From what I have observed, it is related to Maybe typing, but that's pretty much all I have managed to learn.

如果能很好地解释 Just 的含义,我们将不胜感激.

A good explanation of what Just means would be very much appreciated.

推荐答案

其实只是一个普通的数据构造函数,恰好在Prelude中定义,是自动导入的标准库每个模块.

It's actually just a normal data constructor that happens to be defined in the Prelude, which is the standard library that is imported automatically into every module.

定义如下:

data Maybe a = Just a
             | Nothing

那个声明定义了一个类型,Maybe a,它由一个类型变量a参数化,这意味着你可以用任何类型代替<代码>a.

That declaration defines a type, Maybe a, which is parameterized by a type variable a, which just means that you can use it with any type in place of a.

该类型有两个构造函数,Just aNothing.当一个类型有多个构造函数时,这意味着该类型的值必须只用一个可能的构造函数构造.对于这种类型,值要么通过 JustNothing 构造,没有其他(非错误)可能性.

The type has two constructors, Just a and Nothing. When a type has multiple constructors, it means that a value of the type must have been constructed with just one of the possible constructors. For this type, a value was either constructed via Just or Nothing, there are no other (non-error) possibilities.

因为 Nothing 没有参数类型,所以当它用作构造函数时,它会命名一个常量值,该值是所有类型 a 的 Maybe a 类型的成员.但是 Just 构造函数确实有一个类型参数,这意味着当用作构造函数时,它的作用就像一个从 a 类型到 Maybe a 的函数,即它的类型为 a ->也许一个

Since Nothing has no parameter type, when it's used as a constructor it names a constant value that is a member of type Maybe a for all types a. But the Just constructor does have a type parameter, which means that when used as a constructor it acts like a function from type a to Maybe a, i.e. it has the type a -> Maybe a

因此,一个类型的构造函数构建了一个该类型的值;事情的另一面是当您想使用该值时,这就是模式匹配发挥作用的地方.与函数不同的是,构造函数可以用在模式绑定表达式中,这样您就可以对属于具有多个构造函数的类型的值进行case analysis.

So, the constructors of a type build a value of that type; the other side of things is when you would like to use that value, and that is where pattern matching comes in to play. Unlike functions, constructors can be used in pattern binding expressions, and this is the way in which you can do case analysis of values that belong to types with more than one constructor.

为了在模式匹配中使用 Maybe a 值,您需要为每个构造函数提供一个模式,如下所示:

In order to use a Maybe a value in a pattern match, you need to provide a pattern for each constructor, like so:

case maybeVal of
    Nothing   -> "There is nothing!"
    Just val  -> "There is a value, and it is " ++ (show val)

在这种情况下,如果值为 Nothing,第一个模式将匹配,如果值是用 Just 构造的,则第二个模式将匹配.如果第二个匹配,它还会将名称 val 绑定到在构造您要匹配的值时传递给 Just 构造函数的参数.

In that case expression, the first pattern would match if the value was Nothing, and the second would match if the value was constructed with Just. If the second one matches, it also binds the name val to the parameter that was passed to the Just constructor when the value you're matching against was constructed.

也许您已经熟悉这是如何工作的;Maybe 值并没有什么神奇之处,它只是一个普通的 Haskell 代数数据类型 (ADT).但是它被使用了很多,因为它有效地提升"或扩展了一个类型,比如你的例子中的 Integer 到一个新的上下文中,在这个上下文中它有一个额外的值(Nothing>) 代表缺乏价值!然后,类型系统要求您检查该额外值,然后才能获得可能Integer.这可以防止大量错误.

Maybe you were already familiar with how this worked; there's not really any magic to Maybe values, it's just a normal Haskell Algebraic Data Type (ADT). But it's used quite a bit because it effectively "lifts" or extends a type, such as Integer from your example, into a new context in which it has an extra value (Nothing) that represents a lack of value! The type system then requires that you check for that extra value before it will let you get at the Integer that might be there. This prevents a remarkable number of bugs.

今天许多语言通过 NULL 引用处理这种无值"值.杰出的计算机科学家托尼·霍尔(Tony Hoare)(他发明了 Quicksort 并且是图灵奖获得者),将其作为他的 十亿美元的错误".也许类型不是解决这个问题的唯一方法,但它已被证明是一种有效的方法.

Many languages today handle this sort of "no-value" value via NULL references. Tony Hoare, an eminent computer scientist (he invented Quicksort and is a Turing Award winner), owns up to this as his "billion dollar mistake". The Maybe type is not the only way to fix this, but it has proven to be an effective way to do it.

将一种类型转换为另一种类型以便对旧类型的操作可以转换为对新类型进行操作的想法是 Haskell 类型类背后的概念,称为 Functor,其中 Maybe a 有一个有用的实例.

The idea of transforming one type to another one such that operations on the old type can also be transformed to work on the new type is the concept behind the Haskell type class called Functor, which Maybe a has a useful instance of.

Functor 提供了一个名为 fmap 的方法,该方法将覆盖范围从基本类型(例如 Integer)的值的函数映射到范围来自提升类型的值(例如 Maybe Integer).使用 fmap 转换以处理 Maybe 值的函数的工作方式如下:

Functor provides a method called fmap, which maps functions that range over values from the base type (such as Integer) to functions that range over values from the lifted type (such as Maybe Integer). A function transformed with fmap to work on a Maybe value works like this:

case maybeVal of
  Nothing  -> Nothing         -- there is nothing, so just return Nothing
  Just val -> Just (f val)    -- there is a value, so apply the function to it

所以如果你有一个 Maybe Integerm_x 和一个 Int ->int 函数f,你可以做fmap f m_x 将函数f 直接应用于Maybe Integer 而不必担心它是否真的有值.事实上,你可以应用一整条提升的 Integer ->Integer 函数用于 Maybe Integer 值,并且只需担心在完成后显式检查 Nothing 一次.

So if you have a Maybe Integer value m_x and an Int -> Int function f, you can do fmap f m_x to apply the function f directly to the Maybe Integer without worrying if it's actually got a value or not. In fact, you could apply a whole chain of lifted Integer -> Integer functions to Maybe Integer values and only have to worry about explicitly checking for Nothing once when you're finished.

我不确定您对 Monad 的概念有多熟悉,但是您至少之前使用过 IO a 和类型签名 IO a 看起来与 Maybe a 非常相似.尽管 IO 的特殊之处在于它不会向您公开其构造函数,因此只能由 Haskell 运行时系统运行",但它仍然是一个 Functor 此外成为一个 Monad.事实上,在一个重要的意义上,Monad 只是一种特殊的 Functor,具有一些额外的功能,但这不是讨论这个问题的地方.

I'm not sure how familiar you are with the concept of a Monad yet, but you have at least used IO a before, and the type signature IO a looks remarkably similar to Maybe a. Although IO is special in that it doesn't expose its constructors to you and can thus only be "run" by the Haskell runtime system, it's still also a Functor in addition to being a Monad. In fact, there's an important sense in which a Monad is just a special kind of Functor with some extra features, but this isn't the place to get into that.

无论如何,像 IO 这样的 Monad 将类型映射到表示产生值的计算"的新类型,并且您可以通过非常 将函数提升为 Monad 类型fmap 之类的函数称为 liftM,它将常规函数转换为通过计算该函数获得的值的计算".

Anyway, Monads like IO map types to new types that represent "computations that result in values" and you can lift functions into Monad types via a very fmap-like function called liftM that turns a regular function into a "computation that results in the value obtained by evaluating the function."

您可能已经猜到(如果您已经读到这里)Maybe 也是一个 Monad.它代表可能无法返回值的计算".就像 fmap 示例一样,这让您可以进行大量计算,而无需在每一步之后明确检查错误.事实上,Monad 实例的构造方式,对 Maybe 值的计算 stops 一旦 Nothing> 遇到了,所以它有点像在计算过程中立即中止或无价值的返回.

You have probably guessed (if you have read this far) that Maybe is also a Monad. It represents "computations that could fail to return a value". Just like with the fmap example, this lets you do a whole bunch of computations without having to explicitly check for errors after each step. And in fact, the way the Monad instance is constructed, a computation on Maybe values stops as soon as a Nothing is encountered, so it's kind of like an immediate abort or a valueless return in the middle of a computation.

就像我之前说的,Maybe 类型没有任何固有的东西被嵌入到语言语法或运行时系统中.如果 Haskell 默认没有提供它,你可以自己提供它的所有功能!事实上,您无论如何都可以自己重新编写它,使用不同的名称,并获得相同的功能.

Like I said before, there is nothing inherent to the Maybe type that is baked into the language syntax or runtime system. If Haskell didn't provide it by default, you could provide all of its functionality yourself! In fact, you could write it again yourself anyway, with different names, and get the same functionality.

希望您现在了解 Maybe 类型及其构造函数,但如果仍有不清楚的地方,请告诉我!

Hopefully you understand the Maybe type and its constructors now, but if there is still anything unclear, let me know!

这篇关于“正义"是什么意思?Haskell 中的语法是什么意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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