当我尝试编译以下代码时:
matcHelp :: String -> Stack Char -> Stack Char
matcHelp b = mtHelp b (MakeS([])) (MakeS([])) where
mtHelp b result1 result2 =
if (b == [])
then result1 result2
else if head b == '('
then mtHelp (tail b) (push '(' result1) (result2)
else if head b == '['
then mtHelp (tail b) (result1) (push '[' result2)
else if (head b == ')')
then mtHelp (tail b) (popOut result1) (result2)
else if (head b == ']')
then mtHelp (tail b) (result1) (popOut result2)
else mtHelp (tail b) (result1) (result2)
我得到了函数push:
push :: a -> Stack a -> Stack a
push x (MakeS(xs)) = MakeS(x:xs)
应用于太多参数,特别是在实例(push '(' result1)
中。我不明白为什么?
我得到的实际错误是:
Couldn't match expected type `t1 -> t0' with actual type `Stack a0'
In the return type of a call of `push'
Probable cause: `push' is applied to too many arguments
In the second argument of `mtHelp', namely `(push '(' result1)'
In the expression: mtHelp (tail b) (push '(' result1) (result2)
Failed, modules loaded: none.
注意: MakeS是一个数据构造函数
newtype Stack a = MakeS([a]) deriving Show
答案 0 :(得分:5)
问题在于
行if (b == []) then result1 result2
暗示result1
是要应用于result2
的函数。根据您的类型签名,matchHelp
应该返回Stack Char
,因此您在这里犯了错误。
从您的评论中可以看出,您希望从matchHelp
返回多个值。在Haskell中,所有函数始终使用一个参数并返回一个结果。甚至像
(+) :: Int -> Int -> Int
接受一个参数(Int
)并返回一个结果(函数Int -> Int
)。您可以像这样编写类型签名:
(+) :: Int -> (Int -> Int)
但是Haskell无论如何都会为你做这件事。这被称为“currying”。
Haskell返回多个值的方法是返回一个包含这些值的元组或您自己定义的数据结构。
无关,当使用模式匹配和防护时,你的函数与所有if .. then .. else
和head/tail
的“Haskell-y”不是很相似。这是在元组中具有多个返回值的重写函数。
matchHelp :: String -> Stack Char -> (Stack Char, Stack Char)
matchHelp b = mtHelp b (MakeS []) (MakeS [])
where mtHelp [] result1 result2 = (result1, result2)
mtHelp (x:xs) result1 result2
| x == '(' = mtHelp xs (push '(' result1) (result2)
| x == '[' = mtHelp xs (result1) (push '[' result2)
| x == ')' = mtHelp xs (popOut result1) (result2)
| x == ']' = mtHelp xs (result1) (popOut result2)
| otherwise = mtHelp xs result1 result2