我正在练习一些Haskell来更好地理解\
,case.. of
和Maybe
。
我在这里有一个小函数,如果数组为空则应该返回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)
进行了测试,但我仍然遇到同样的错误。
答案 0 :(得分:6)
将函数的返回类型设置为
Maybe a
,因为在一种情况下,它应返回Int
,而在另一种情况下返回[Int]
。
Haskell 静态类型。这意味着它不能 - 在运行时 - 具有不同的返回类型。它只能有一种返回类型。 a
不是 ad hoc 类型(在某种意义上它可以是运行时的任何类型)。这意味着a
将在编译时根据其他参数的类型确定。
例如,您可以编写:foo :: a -> a -> a
来指定如果foo
需要两个Int
(在编译时再次知道),结果将是Int
。
然而,您可以使用Either a b
表示您将 返回Left a
或Right 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
)。