[作者六年后的编辑] 这是一个不必要的长回答,我不确定为什么它被接受了。像最高投票的答案建议的那样使用maybe
或Data.Maybe.fromMaybe
。接下来的内容更像是一种思想实验,而不是实用建议。
因此,您正在尝试创建适用于各种不同类型的函数。这是制作类的好时机。如果您已经在Java或C ++中编程,那么Haskell中的类有点类似于这些语言中的接口。
class Nothingish a where
nada :: a
这个类定义了一个值nada
,它应该是该类等同于Nothing
的值。现在让我们来玩点有趣的事情:创建这个类的实例!
instance Nothingish (Maybe a) where
nada = Nothing
对于类型为
Maybe a
的值,类似于Nothing的值是
Nothing
!这将在一分钟内成为一个奇怪的例子。但在此之前,让我们也将列表作为该类的一个实例。
instance Nothingish [a] where
nada = []
一个空列表有点像“Nothing”,对吧?所以对于一个字符串(它是一个字符列表),它将返回空字符串""
。
数字也是一种简单的实现。你已经表明0显然代表数字的“无”。
instance (Num a) => Nothingish a where
nada = 0
这个只有在文件开头加入特殊行才能起作用。
{-# LANGUAGE FlexibleInstances, UndecidableInstances, OverlappingInstances #-}
或者在编译时,您可以设置这些语言编译指示符的标志。不用担心它们,它们只是让更多东西工作的魔法。
现在您已经有了这个类和它的实例......现在让我们重新编写您的函数来使用它们!
eliminate :: (Nothingish a) => Maybe a -> a
eliminate (Just a) = a
eliminate Nothing = nada
注意我只把0
改成了nada
,其余的代码保持不变。我们来试试!
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,看到了吗?这是一个奇怪的例子,在Maybe中嵌套了一个Maybe。无论如何...那么消除Nothing
呢?结果类型是不确定的。它不知道我们期望什么类型。所以我们必须告诉它我们想要的类型。
ghci> eliminate Nothing :: Int
0
现在可以尝试将其他类型传入该函数,你会发现对于每种类型都返回了nada
。因此,当您在使用combine
函数时,会得到以下结果:
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" 的类型,或指定您期望的返回类型。
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)
或者,您可以通过在源代码中明确指定函数的类型签名来限制函数允许的类型。如果函数的逻辑使用方式是仅与相同类型的参数一起使用,则这是有意义的。
combine :: (Nothingish a) => Maybe a -> Maybe a -> Maybe a -> (a,a,a)
combine a b c = (eliminate a, eliminate b, eliminate c)
现在,只有当三个Maybe的类型相同时,它才能工作。这样做可以推断出
Nothing
与其他内容具有相同的类型。
ghci> combine (Just 2) Nothing (Just 4)
(2,0,4)
没有歧义,太好了!但是现在混合使用是错误的,就像我们之前做的一样。
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
我认为那是一个够长且过度夸张的回答。祝你愉快。
Nothing
所代表的。并不存在一个总函数Maybe a -> a
,因为没有一种统一的方式可以将Nothing
转换成a
。你能做的最好的事情就是编写一个函数(Maybe a, Maybe b, Maybe c) -> Maybe (a, b, c)
。 - Tom CrockettMaybe a
的常见方法(标准函数),并没有专注于fromJust
或其他部分函数作为唯一可能性。(不是说我不同意你的答案,在这里教授类型类似乎很合适)。 - Thomas M. DuBuisson