我有一个类似于的自定义数据类型:
data Token = Number Int
| Otherthings
我希望能够以一种方式使用“数字”而在另一种方式中使用其他东西。所以我可以成功创建一个案例陈述,如:
parse x = case x of
Number y -> y
然后成功地采取了:
let x = Number 7 in parse x
并评估为7.但是,当我尝试将“解析”功能更改为:
parse [] = []
parse (x:xs) = case x of
Number y -> y
我收到错误:
Couldn't match expected type `[a0]' with actual type `Int'
In the expression: y
In a case alternative: Number y -> y
In the expression: case x of { Number y -> y }
为什么这不能以这种方式工作以及解决这个问题的正确方法是什么?非常感谢!
答案 0 :(得分:6)
分别查看parse
定义的两个部分的类型。
parse :: [a] -> [b] -- both the []'s are lists of some (possibly different) type
parse [] = []
和
parse :: [Token] -> Int -- y, the function's return value, is an Int.
parse (x:xs) = case x of
Number y -> y
你可以看到a ~ Token
工作正常,[b] ~ Int
不起作用:Int不是某个列表。 (错误消息正在使用a0
,我正在使用b
。)
解决这个问题的方法是考虑你希望parse
返回什么类型,并确保其定义的所有部分都与之匹配。我不确定你想要parse
做什么,所以我不能在那里给出明确的答案。
答案 1 :(得分:2)
parse
的两个定义有不同的类型。 parse []
返回一个列表,而parse (x:xs)
返回一个裸号。
你可以使它工作,例如,通过在单个列表中返回数字
parse [] = []
parse (x:xs) = case x of
Number y -> [y]
或通过返回空列表案例的数字
parse [] = 0
parse (x:xs) = case x of
Number y -> y
或以其他多种方式,取决于您想要达到的目标。
答案 2 :(得分:1)
问题是你的第二个parse
函数在传递空列表时返回List
并且在传递非空Int
时尝试返回List
}。这就是编译器所抱怨的。
当您使用案例或模式匹配时,最好编写所有可能的构造函数。想想当有人使用parse
调用时,[Otherthings, Number 3]
函数会发生什么。
您应该使用Maybe
代替并匹配Data type
的所有构造函数:
parse [] = Nothing
parse (x:xs) = case x of
Number y -> Just y
Otherthings -> Nothing
答案 3 :(得分:0)
你已经拥有
parse x = case x of
Number y -> y
你想拥有parseList,它看起来像:
parseList = map parse
或以更详细的方式撰写:
parseList [] = []
parseList (x:xs) = parse x : parseList xs
或
parseList [] = []
parseList (x:xs) = case x of
Number y -> y : parseList xs
也许你忘了解析rest元素,只解析第一个