[从作者编辑,6 年后] 这是一个不必要的冗长答案,我不确定它为什么被接受。按照最高投票答案中的建议使用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-like 值是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 in a Maybe。无论如何...eliminate 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
嗯,我认为这是一个足够长且夸大其词的答案。享受吧。