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

How I can set the signature of a function right?

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

我这里有这个小函数,如果数组为空,return Nothing,如果 y 等于数组 xs 的头部,Just y Just (tail xs)如果y不等于数组头部xs.

我将函数的 return 类型设置为 Maybe a 因为在一种情况下它应该 return 一个 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] 匹配。 Maybe a 中的 a 不是通用的,还是受我 "used" a 作为 Just y 中的 Int 这一事实的影响部分?

编辑: 好的,我的建议是 bs,我在 then 和 else 部分用 Just (tail xs) 测试了它,但我仍然遇到同样的错误。

set the return type of the function to Maybe a because in one case it should return an Int and in the other an [Int].

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

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

但是您可以使用 Either a b 表示您将 return 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是一个typeclass,指定存在一个我们可以使用的函数(==) :: a -> a -> Bool。否则无法在函数体中使用 ==

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