[从作者编辑,6 年后] 这是一个不必要的长答案,我不确定它为什么被接受。使用maybe
或Data.Maybe.fromMaybe
按照最高投票的答案中的建议。接下来是一个思想实验,而不是实际的建议。
因此,您正在尝试创建一个适用于多种不同类型的函数。这是上课的好时机。如果您使用 Java 或 C++ 编程,那么 Haskell 中的类有点像这些语言中的接口。
class Nothingish a where
nada :: a
这个类定义了一个值nada
,它应该是类的等价物Nothing
。现在有趣的部分:制作这个类的实例!
instance Nothingish (Maybe a) where
nada = Nothing
对于 type 的值Maybe a
,Nothing-like 值是,嗯,Nothing
!这将是一个奇怪的例子。但在那之前,让我们也让列表成为这个类的一个实例。
instance Nothingish [a] where
nada = []
一个空列表有点像什么都没有,对吧?所以对于一个字符串(它是一个字符列表),它将返回空字符串,""
.
数字也是一个简单的实现。您已经指出 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
好吧,我认为这是一个足够长和夸大其词的答案。享受。