【问题标题】:How to declare function (type misunderstanding Maybe)如何声明函数(类型误解Maybe)
【发布时间】:2010-12-06 18:59:55
【问题描述】:

我需要一个像这样工作的函数:

some :: (Int, Maybe Int) -> Int
some a b
     | b == Nothing = 0
     | otherwise = a + b

用例:

some (2,Just 1)
some (3,Nothing)
map some [(2, Just 1), (3,Nothing)]

但我的代码引发了错误:

The equation(s) for `some' have two arguments,
but its type `(Int, Maybe Int) -> Int' has only one

我不明白。

提前致谢。

【问题讨论】:

  • some = uncurry $ maybe 0 . (+)
  • 您可能对如何使用Maybe a 类型answered here 的更一般的问题感兴趣。

标签: haskell


【解决方案1】:

当你写作时

foo x y = ...

这是 curried 函数的符号,其类型如下:

foo :: a -> b -> c

你已经声明你的函数需要一个元组,所以你必须写它:

some :: (Int, Maybe Int) -> Int
some (x, y) = ...

但是 Haskell 的约定通常是采用前咖喱形式的参数。看到函数将元组作为参数是非常罕见的。

对于你问题的另一部分,你可能想用模式匹配来表达它。你可以说:

foo :: Maybe Int -> Int
foo Nothing = 0
foo (Just x) = x + 1

将这一点概括为 OP 的问题留给读者作为练习。

【讨论】:

  • 谢谢。模式匹配是我需要的。
  • 我可能会写some a b = fromMaybe 0 (fmap (+ a) b)而不是模式匹配,然后将其指向some a = fromMaybe 0 . fmap (+ a)。
  • @John,您认为向尚未掌握柯里化和模式匹配的人建议使用 Functor 和无点样式是否有帮助?
【解决方案2】:

您的错误并非来自对Maybe 的误解:some 的类型签名表明它需要一对(Int, Maybe Int),而在您的定义中您为其提供了两个参数。因此,定义应以some (a,b) 开头以匹配类型签名。

解决问题的一种方法(也更习惯使用模式匹配)是:

some :: (Int, Maybe Int) -> Int
some (a, Nothing) = a
some (a, Just b) = a + b

还值得注意的是,除非您有充分的理由使用元组作为输入,否则您可能不应该这样做。如果您的签名改为some :: Int -> Maybe Int -> Int,您将拥有一个包含两个参数的函数,可以是curried。然后你会写类似的东西

some :: Int -> Maybe Int -> Int
some a Nothing = a
some a (Just b) = a + b

此外,您可能希望添加以下直接概括:所有Num 类型都是相加的,因此您不妨这样做

some :: (Num n) => n -> Maybe n -> n
some a Nothing = a
some a (Just b) = a + b

(我违反了将 a、b、c... 用于类型变量的常见做法,以免混淆 OP,因为他将 a 和 b 绑定到 some 的参数)。

【讨论】:

    猜你喜欢
    • 2019-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多