如何在Haskell中获得Maybe的价值 [英] How to get the value of a Maybe in Haskell

查看:120
本文介绍了如何在Haskell中获得Maybe的价值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对Haskell比较陌生,开始读《真实世界的Haskell》.

I'm relatively new to Haskell and began to read "Real World Haskell".

我偶然发现了Maybe类型,例如,有一个关于如何从Just 1接收实际值的问题.

I Just stumbled over the type Maybe and have a question about how to receive the actual value from a Just 1 for example.

我写了以下代码:

combine a b c = (eliminate a, eliminate b, eliminate c)
                where eliminate (Just a) = a
                      eliminate Nothing = 0

如果我使用,这可以正常工作

This works fine if I use:

combine (Just 1) Nothing (Just 2)

但是,例如,如果我将1更改为字符串,那将无法正常工作.

But if I change, for example, 1 to a String it doesn't work.

我想我知道为什么:因为eliminate必须返回一种类型,在这种情况下为Int.但是如何更改eliminate至少处理字符串(或者可能处理所有类型)?

I think I know why: because eliminate has to give back one type, which is, in this case, an Int. But how can I change eliminate to deal at least with Strings (or maybe with all kind of types)?

推荐答案

[作者编辑,六年后]这是一个不必要的冗长答案,我不确定为什么会接受.按照最高建议的答案中的建议使用maybeData.Maybe.fromMaybe.接下来的更多是思想实验,而不是实践建议.

[edit from Author, 6 years later] This is a needlessly long answer, and I'm not sure why it was accepted. Use maybe or Data.Maybe.fromMaybe as suggested in the highest upvoted answer. What follows is more of a thought experiment rather than practical advice.

因此,您试图创建一个适用于多种不同类型的函数.这是上课的好时机.如果您使用Java或C ++进行编程,那么Haskell中的类就像是这些语言的接口.

So you're trying to create a function that works for a bunch of different types. This is a good time to make a class. If you've programmed in Java or C++, a class in Haskell is kind of like an interface in those languages.

class Nothingish a where
    nada :: a

此类定义了一个值nada,该值应该等同于该类与Nothing的值.现在有趣的部分:创建此类的实例!

This class defines a value nada, which is supposed to be the class's equivalent of Nothing. Now the fun part: making instances of this class!

instance Nothingish (Maybe a) where
    nada = Nothing

对于Maybe a类型的值,类似Nothing的值就是Nothing!一分钟后,这将是一个奇怪的例子.但是在此之前,让我们也列出此类的实例.

For a value of type Maybe a, the Nothing-like value is, well, Nothing! This will be a weird example in a minute. But before then, let's make lists an instance of this class too.

instance Nothingish [a] where
    nada = []

一个空列表有点像什么,不是吗?因此,对于String(它是Char的列表),它将返回空字符串"".

An empty list is kind of like Nothing, right? So for a String (which is a list of Char), it will return the empty string, "".

数字也很容易实现.您已经表明0显然表示数字无".

Numbers are also an easy implementation. You've already indicated that 0 obviously represents "Nothingness" for numbers.

instance (Num a) => Nothingish a where
    nada = 0

除非您在文件顶部放置特殊的行,否则此行实际上将不起作用

This one will actually not work unless you put a special line at the top of your file

{-# LANGUAGE FlexibleInstances, UndecidableInstances, OverlappingInstances #-}

或者在编译它时,可以为这些语言编译指示设置标志.不用担心它们,它们只是神奇的东西,可以使更多的东西起作用.

Or when you compile it you can set the flags for these language pragmas. Don't worry about them, they're just magic that makes more stuff work.

所以现在您有了这个类以及它们的这些实例...现在让我们重新编写函数以使用它们!

So now you've got this class and these instances of it...now let's just re-write your function to use them!

eliminate :: (Nothingish a) => Maybe a -> a
eliminate (Just a) = a
eliminate Nothing  = nada

注意,我只将0更改为nada,其余相同.让我们旋转一下吧!

Notice I only changed 0 to nada, and the rest is the same. Let's give it a spin!

ghci> eliminate (Just 2)
2
ghci> eliminate (Just "foo")
"foo"
ghci> eliminate (Just (Just 3))
Just 3
ghci> eliminate (Just Nothing)
Nothing
ghci> :t eliminate
eliminate :: (Nothingish t) => Maybe t -> t
ghci> eliminate Nothing
error! blah blah blah...**Ambiguous type variable**

非常适合于价值和东西.注意(Just Nothing)变成Nothing,看到了吗?那是一个怪异的例子,也许就是也许.无论如何... eliminate Nothing呢?好吧,结果类型是模棱两可的.它不知道我们在期待什么.所以我们必须告诉它想要什么类型.

Looks great for values and stuff. Notice the (Just Nothing) turns into Nothing, see? That was a weird example, a Maybe in a Maybe. Anyways...what about eliminate Nothing? Well, the resultant type is ambiguous. It doesn't know what we are expecting. So we have to tell it what type we want.

ghci> eliminate Nothing :: Int
0

继续尝试其他类型的产品;您会看到它每个获得nada.因此,现在,当将此功能与combine函数一起使用时,会得到以下信息:

Go ahead and try it out for other types; you'll see it gets nada for each one. So now, when you use this function with your combine function, you get this:

ghci> let combine a b c = (eliminate a, eliminate b, eliminate c)
ghci> combine (Just 2) (Just "foo") (Just (Just 3))
(2,"foo",Just 3)
ghci> combine (Just 2) Nothing (Just 4)
error! blah blah Ambiguous Type blah blah

请注意,您仍然必须指出"Nothing"是什么类型,或者指出期望的返回类型.

Notice you still have to indicate what type your "Nothing" is, or indicate what return type you expect.

ghci> combine (Just 2) (Nothing :: Maybe Int) (Just 4)
(2,0,4)
ghci> combine (Just 2) Nothing (Just 4) :: (Int, Int, Int)
(2,0,4)

或者,您可以通过将函数的类型签名显式放置在源代码中来限制函数允许的类型.如果该函数的逻辑用法是仅与相同类型的参数一起使用,则这是有道理的.

Or, you could restrict the types that your function allows by putting its type signature explicitly in the source. This makes sense if the logical use of the function would be that it is only used with parameters of the same type.

combine :: (Nothingish a) => Maybe a -> Maybe a -> Maybe a -> (a,a,a)
combine a b c = (eliminate a, eliminate b, eliminate c)

现在,仅当所有三个Maybe事物都属于同一类型时,它才起作用.这样,就可以推断Nothing与其他类型相同.

Now it only works if all three Maybe things are the same type. That way, it will infer that the Nothing is the same type as the others.

ghci> combine (Just 2) Nothing (Just 4)
(2,0,4)

毫不含糊,是的!但是现在像以前一样,混合和匹配是一个错误.

No ambiguity, yay! But now it is an error to mix and match, like we did before.

ghci> combine (Just 2) (Just "foo") (Just (Just 3))
error! blah blah  Couldn't match expected type  blah blah
blah blah blah    against inferred type         blah blah

嗯,我认为这是一个足够长且过于夸张的答案.享受.

Well, I think that was a sufficiently long and overblown answer. Enjoy.

这篇关于如何在Haskell中获得Maybe的价值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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