haskell的新手,我决定尝试实现一个迷你反向抛光符号功能:
采用list
类型的int
和字符串运算符('*','+','/','-'
)
将运算符应用于tail
元素和tail-1
元素
返回结果list
,并弹出操作中涉及的两个元素,并将结果元素附加到尾部,如下所示:
Where e0 = original element at index 0
r = result of the operation:
result = [e0,e1,e2...r] (elements popped off: eN, eN-1)
这是我到目前为止的代码:
import Data.List
import System.IO
step :: [Int] -> String -> [Int]
step stack operator
| (x:y:ys) "*" = (x * y):ys
| (x:y:ys) "+" = (x + y):ys
| (x:y:ys) "-" = (x - y):ys
| (x:y:ys) "/" = (x / y):ys
它给了我以下编译错误:
• Couldn't match expected type ‘[Char] -> Bool’
with actual type ‘[a3]’
• The function ‘x : y : ys’ is applied to one argument,
but its type ‘[a3]’ has none
In the expression: (x : y : ys) "/"
In a stmt of a pattern guard for
an equation for ‘step’:
(x : y : ys) "/"
我相信这是我语法错误的结果, 欢迎任何帮助!
答案 0 :(得分:3)
您已经正确实现了该功能,但是语法略有错误-当您要使用模式匹配时使用了防护措施:
Bool
类型的有效表达式。)在您的代码中,您使用过防护,但是您确实想要模式匹配,如下所示:
step :: [Int] -> String -> [Int]
step (x:y:ys) "*" = (x * y):ys
step (x:y:ys) "+" = (x + y):ys
step (x:y:ys) "-" = (x - y):ys
step (x:y:ys) "/" = (x / y):ys
但是,这仍然会产生错误:
* No instance for (Fractional Int) arising from a use of `/'
* In the first argument of `(:)', namely `(x / y)'
In the expression: (x / y) : ys
In an equation for `step': step (x : y : ys) "/" = (x / y) : ys
这个错误非常清楚:您正在尝试/
一个整数,但是整数不是Fractional
,所以您不能这样做。如果要整数除法,可以将其替换为div x y
,否则可以在类型签名中将Int
更改为Float
,以允许使用非整数值。
但是,即使进行了此更改,仍然存在一个细微的错误:如果列表中的元素少于两个,或者使用了不受支持的运算符,该怎么办?正确的做法是使用step _ _ = (something)
在结尾进行模式匹配,其中_
是一种特殊的语法,可以匹配所有内容。 (或者,如果您想参考step stack operator = (something)
和stack
来获取类似错误消息之类的信息,也可以使用operator
。
编辑:在下面的评论中,@ chepner建议了另一种使用模式匹配和防护的方法:
step :: [Int] -> String -> [Int]
step (x:y:ys) op
| op == "*" = (x * y):ys
| op == "+" = (x + y):ys
-- etc.
| otherwise = (some error case)
这再次说明了两者之间的区别:模式匹配用于将第一个参数分解为x
,y
和ys
,而后卫用于布尔条件(与{ {1}}实际上在前奏中定义为等于otherwise
)。