如何声明函数(类型误解可能)

时间:2010-12-06 10:43:04

标签: haskell

我需要一个功能如下:

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

我不明白。

提前致谢。

2 个答案:

答案 0 :(得分:10)

写作时

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的问题进行概括是留给读者的练习。

答案 1 :(得分:7)

您的错误不是来自对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,因为他将ab绑定到{的参数{1}})。