如何获得“价值” Haskell中的一个Maybe [英] How to get the "Value" of an Maybe in Haskell

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

问题描述

我对Haskell比较新,并开始阅读Real World Haskell。我只是偶然发现了这种类型也许有一个关于如何从Just 1接收实际值的问题。我写了以下代码:

  combine abc =(消除a,消除b,消除c)
where消除只要a)= a
消除无= 0

如果我使用

  combine(Just 1)Nothing(Just 2)

但是,如果我改变了,例如1改为一个字符串,它不起作用。
我想我知道为什么:因为 elimination 必须返回一个类型,在这种情况下,是 Int 。但是我怎样才能改变消除来至少处理字符串? (或可能与所有类型?)

解决方案

不必要的长答案,我不确定它为什么被接受。使用也许 Data.Maybe.fromMaybe ,就像最高的答案中所建议的那样。接下来的是更多的思考实验,而不是实际的建议。

所以你试图创建一个适用于一堆不同类型的函数。这是上课的好时机。如果您使用Java或C ++编程,Haskell中的类就像这些语言中的接口。

  class Nothingish a where 
nada :: a

该类定义了一个值 nada ,它应该是类的等价物 Nothing

  instance Nothingish(也许a)其中
nada = Nothing

对于类型也许a 的值,没有什么价值的是, Nothing !这将在一分钟内成为一个奇怪的例子。

  instance Nothingish [a]其中
nada = []

空列表有点像Nothing,对吧?所以对于String(它是Char的列表),它将返回空字符串



数字也是一个简单的实现。您已经指出0对数字显然表示虚无。

  instance(Num a)=>没有什么其中的
nada = 0



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

或者当您编译它时,您可以设置这些语言编译指示的标志。不要担心它们,它们只是使更多东西有效的魔法。



所以,现在你已经有了这个类以及它的这些实例...现在

  elimination ::(Nothingish a)=>我们只需重新编写函数即可使用它们!也许是 - > a 
消除(Just a)= a
消除Nothing = nada

我只将 0 更改为 nada ,其余部分相同。让我们一起旋转!

  ghci>消除(只是2)
2
ghci>消除(Justfoo)
foo
ghci>消除(Just(Just 3))
只需3
ghci>消除(Just Nothing)
Nothing
ghci> :t消除
elimination ::(Nothingish t)=>也许t - > t
ghci>消除无
错误!等等等等...... **不明确的类型变量**

看起来非常适合值和东西。注意(Just Nothing)会变成Nothing,看看?这是一个奇怪的例子,也许在一个也许。无论如何... >消除无?那么,最终的类型是不明确的。它不知道我们期待什么。所以我们必须告诉它我们想要什么类型。

  ghci>消除Nothing :: Int 
0

继续尝试其他类型;你会看到它为每一个获得 nada 。所以,现在,当你在 combine 函数中使用这个函数时,你会得到这个:

  ghci的>让联合一个b c =(消除a,消除b,消除c)
ghci>合并(Just 2)(Justfoo)(Just(Just 3))
(2,foo,Just 3)
ghci>结合(只是2)没有(只是4)
错误! blah blah不明确的类型等等等等

注意,您仍然必须指出您的Nothing是什么类型,或者请指出您期望的退货类型。

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

或者,您可以通过将其类型签名显式地放在源代码中来限制您的函数允许的类型。这是合理的,如果该函数的逻辑用法是,它只能用于相同类型的参数。

  combine: :(Nothingish a)=>也许是 - >也许是 - >也许是 - > (a,a,a)
合并abc =(消除a,消除b,消除c)

现在只有在所有三种可能的东西都是相同类型的情况下才有效。这样,它会推断 Nothing 与其他类型相同。

  ghci的>合并(Just 2)Nothing(Just 4)
(2,0,4)

没有歧义,耶!但现在混合和匹配是一个错误,就像我们以前做过的那样。

  ghci> (Just 2)(Justfoo)(Just(Just 3))
错误! blah blah无法匹配预期的类型等等等等等等等等等等等等等等等等等等等等等等等等等等等等等等等等等等等等等等等。 >那么,我认为这是一个足够长且过分夸大的答案。享受。

I'm relatively new to Haskell and began to read "Real World Haskell". I Just stumbled over the type Maybe a have a question about how to receive the actual value from a "Just 1" for example. I have written following code:

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)

But if I change, for example, 1 to a String it doesn't work. 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?)

解决方案

[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.

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

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

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 = []

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, "".

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

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**

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

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

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)

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天全站免登陆