我有下面的函数,它应该返回列表的倒数第二个元素:
myButLast :: [a] -> a
myButLast [] = error "List has less than one element!"
myButLast [x] = error "List has less than one element!"
myButLast [x,_] = x
myButLast (_:xs) = myButLast xs当我将它加载到ghci中时,它适用于所有特殊情况,但当我尝试使用HSpec测试它时,我在运行此规范时出现错误:
main :: IO ()
main = hspec $ do
describe "myButLast" $ do
-- removed other specs --
it "throws an error when called with a singleton list" $
myButLast [1] `shouldThrow` anyErrorCall以下是错误消息:
No instance for (Num (IO a0)) arising from the literal `1'
Possible fix: add an instance declaration for (Num (IO a0))
In the expression: 1
In the first argument of `myButLast', namely `[1]'
In the first argument of `shouldThrow', namely `myButLast [1]'有趣的是,在测试myButLast []而不是myButLast [1]时,编译器不会报错,尽管两个表达式的结果定义完全相同。
发布于 2014-07-25 22:12:44
正如西蒙所指出的:
myButLast [1] 只是有一个错误的类型,即Num a => a,而shouldThrow需要一个IO a类型的第一个参数。
所以,更有趣的问题是:
编译器为什么不抱怨 myButLast []**?**的类型
这样做的原因是:由于文字[]也可以是[IO a]类型,编译器会推断myButLast []的类型为IO a,因为这是唯一有效的shouldThrow第一个参数。
发布于 2018-03-29 11:00:31
要回答问题背后的问题:要编写测试,您需要使用evaluate
import Control.Exception.Base
main :: IO ()
main = hspec $ do
describe "myButLast" $ do
it "throws an error when called with a singleton list" $
evaluate (myButLast [1]) `shouldThrow` anyErrorCallhttps://stackoverflow.com/questions/24953562
复制相似问题