[英]testing functions that return a Maybe Monad
说我有一个功能:
safeHead :: [a] -> Maybe a
safeHead [] = Nothing
safeHead xs = Just $ head xs
并测试:
describe "Example.safeHead" $ do
it "returns the head" $ do
safeHead [1,2,3] `shouldBe` Just 1
it "returns Nothing for an empty list" $
safeHead [] `shouldBe` Nothing
然而,这会产生:
No instance for (Eq a0) arising from a use of ‘shouldBe’
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance (Eq a, Eq b) => Eq (Either a b)
-- Defined in ‘Data.Either’
instance forall (k :: BOX) (s :: k). Eq (Data.Proxy.Proxy s)
-- Defined in ‘Data.Proxy’
instance (GHC.Arr.Ix i, Eq e) => Eq (GHC.Arr.Array i e)
-- Defined in ‘GHC.Arr’
...plus 88 others
In the second argument of ‘($)’, namely
‘safeHead [] `shouldBe` Nothing’
In a stmt of a 'do' block:
it "returns Nothing for an empty list"
$ safeHead [] `shouldBe` Nothing
In the second argument of ‘($)’, namely
‘do { it "returns the head"
$ do { safeHead [...] `shouldBe` Just 1 };
it "returns Nothing for an empty list"
$ safeHead [] `shouldBe` Nothing }’
为什么? 我该如何解决?
正如user2407038评论的那样,编译器不知道如何实例化a
。 他提出的解决办法是可能是最好的一个-你应该指定类型的a
明确的。
但为了完整性,我想指出,还有其他解决方案, 扩展默认规则 :
{-# LANGUAGE ExtendedDefaultRules #-}
describe "Example.safeHead" $ do
it "returns the head" $ do
safeHead [1,2,3] `shouldBe` Just 1
it "returns Nothing for an empty list" $
safeHead [] `shouldBe` Nothing
扩展修改标准默认规则以包含更多情况,例如Eq
类型。
补充:经过一番思考后,我重新考虑了一下我的回答。 多态函数的单元测试结果不应该依赖于实例化类型变量的特定方式。 所以可能扩展的默认规则是测试中的正确的东西? 我从来没有把它用作真正的代码,所以我不能肯定地说,但它绝对值得考虑。
shouldBe :: (Eq a, Show a) => a -> a -> Expectation
safeHead :: [a] -> Maybe a
[] :: [a]
safeHead [] :: Maybe a
Nothing :: Maybe a
shouldBe (safeHead []) :: (Eq a, Show a) => Maybe a -> Expectation
shouldBe (safeHead []) Nothing :: Expectation -- but what's `a`?
如你所见, a
完全是模棱两可的。 它可以是具有Show
和Eq
实例的任何类型。 这也是您的错误消息的一部分:
No instance for (Eq a0) arising from a use of ‘shouldBe’ The type variable ‘a0’ is ambiguous
选择一个:
it "returns Nothing for an empty list" $
safeHead [] `shouldBe` (Nothing :: Maybe ())
当您使用它时,使用safeHead
验证safeHead
是否像head
safeHead
工作:
it "returns Just (head xs) for a non-empty list" $ property $ \(NonEmpty xs) ->
safeHead xs `shouldBe` (Just (head xs) :: Maybe Integer)
此代码测试一个返回“Just”值的Maybe Monad:
import Test.Tasty
import Test.Tasty.HUnit
import Data.List
main = defaultMain tests
tests = testGroup "Tests uncons form Data.List"
[testCase "Show uncons [1,2,3,4] = (1, [2,3,4])" $
Just (1,[2,3,4]) @=? (uncons [1,2,3,4])]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.