1

我有一个自定义数据类型,类似于:

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 }

为什么这不起作用,解决这个问题的正确方法是什么?非常感谢!

4

4 回答 4

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什么,所以我不能在那里给出明确的答案。

于 2013-09-15T18:51:56.267 回答
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

或以其他多种方式,具体取决于您想要实现的目标。

于 2013-09-15T18:52:22.323 回答
1

问题是您的第二个parse函数在传递空列表时返回 a ,并且在传递非List空列表时尝试返回 a 。这就是编译器所抱怨的。IntList

当您使用大小写或模式匹配时,编写所有可能的构造函数是一种很好的做法。想想parse当有人调用它时你的函数会发生什么[Otherthings, Number 3]

您可能应该Maybe改用并匹配以下的所有构造函数Data type

parse []     = Nothing
parse (x:xs) = case x of
    Number y    -> Just y
    Otherthings -> Nothing
于 2013-09-15T18:48:21.007 回答
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

可能你忘了解析其余元素,只解析第一个

于 2013-09-15T20:50:20.230 回答