我如何设置函数的签名是正确的?

时间:2017-07-19 18:48:00

标签: haskell maybe

我正在练习一些Haskell来更好地理解\case.. ofMaybe

我在这里有一个小函数,如果数组为空则应该返回Nothing,如果y等于数组xs的头部,则Just y如果y是Just (tail xs)不等于数组xs的头部。

我将函数的返回类型设置为Maybe a,因为在一种情况下,它应该返回Int而在另一种情况下返回[Int]

funct :: Int -> [Int] ->  Maybe a
funct = \y xs -> case xs of
            [] -> Nothing
            xs -> if ((head xs) == y)
                        then Just y
                        else Just (tail xs)

我错过了什么?我收到的错误是a类型与[Int]无法匹配。 a中的Maybe a不是通用的,还是因为我在a部分中使用Int作为Just y这一事实而受到影响?

编辑:好的我的建议是bs,我在当时和其他部分用Just (tail xs)进行了测试,但我仍然遇到同样的错误。

1 个答案:

答案 0 :(得分:6)

  

将函数的返回类型设置为Maybe a,因为在一种情况下,它应返回Int,而在另一种情况下返回[Int]

Haskell 静态类型。这意味着它不能 - 在运行时 - 具有不同的返回类型。它只能有一种返回类型。 a不是 ad hoc 类型(在某种意义上它可以是运行时的任何类型)。这意味着a将在编译时根据其他参数的类型确定。

例如,您可以编写:foo :: a -> a -> a来指定如果foo需要两个Int(在编译时再次知道),结果将是Int

然而,您可以使用Either a b表示您将 返回Left aRight b。所以你可以把它重写为:

funct :: Int -> [Int] ->  Maybe (Either Int [Int])
funct = \y xs -> case xs of
            [] -> Nothing
            xs -> if ((head xs) == y)
                        then Just (Left y)
                        else Just (Right (tail xs))

你的功能非常冗长,你可以按照以下方式使其更加清晰和紧凑:

funct :: Int -> [Int] ->  Maybe (Either Int [Int])
funct _ [] = Nothing
funct y (h:t) | h == y = Just (Left y)
              | otherwise = Just (Right t)

此外,我们可以将其概括为:

funct :: Eq a => a -> [a] ->  Maybe (Either a [a])
funct _ [] = Nothing
funct y (h:t) | h == y = Just (Left y)
              | otherwise = Just (Right t)

此处Eq类型类,它指定存在我们可以使用的函数(==) :: a -> a -> Bool。否则,无法在函数体中使用==

此外,我们在每个子句的头部使用模式[]是描述空列表的模式。另一方面,(h:t)是描述包含至少一个元素的列表的模式:头部h,后跟一个(可能是空尾t)。