Haskell HSpec Nothing预期无法编译

Haskell HSpec Nothing预期无法编译,haskell,hspec,Haskell,Hspec,我正在学习Haskell并编写了以下函数: safeHead :: [a] -> Maybe a safeHead [] = Nothing safeHead (x:xs) = Just x palindrome :: (Eq a) => [a] -> [a] palindrome xs = xs ++ reverse xs 我现在尝试用HSpec测试它: import Test.Hspec main :: IO () main = hspec spec spec ::

我正在学习Haskell并编写了以下函数:

safeHead :: [a] -> Maybe a
safeHead [] = Nothing
safeHead (x:xs) = Just x
palindrome :: (Eq a) => [a] -> [a]
palindrome xs = xs ++ reverse xs
我现在尝试用HSpec测试它:

import Test.Hspec

main :: IO ()
main = hspec spec

spec :: Spec
spec =

  describe "safeHead" $
    it "should return Nothing for empty list" $
      safeHead [] `shouldBe` Nothing
但这无法编译:

Error:(14, 19) ghc: 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 (Maybe a) -- Defined in ‘GHC.Base’
      instance Eq a => Eq (GHC.Real.Ratio a) -- Defined in ‘GHC.Real’
      instance Eq Ordering -- Defined in ‘ghc-prim-0.4.0.0:GHC.Classes’
      ...plus 31 others
    In the second argument of ‘($)’, namely
      ‘safeHead [] `shouldBe` Nothing’
    In the second argument of ‘($)’, namely
      ‘it "should return Nothing for empty list"
       $ safeHead [] `shouldBe` Nothing’
    In the expression:
      describe "safeHead"
      $ it "should return Nothing for empty list"
        $ safeHead [] `shouldBe` Nothing
我也试过:

safeHead :: (Eq a) => [a] -> Maybe a
safeHead [] = Nothing
safeHead (x:xs) = Just x
但在以下情况下,这仍然是失败的:

Error:(14, 19) ghc: 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 Eq Data.Monoid.All -- Defined in ‘Data.Monoid’
      instance forall (k :: BOX) (f :: k -> *) (a :: k).
               Eq (f a) =>
               Eq (Data.Monoid.Alt f a)
        -- Defined in ‘Data.Monoid’
      ...plus 43 others
    In the second argument of ‘($)’, namely
      ‘safeHead [] `shouldBe` Nothing’
    In the second argument of ‘($)’, namely
      ‘it "should return Nothing for empty list"
       $ safeHead [] `shouldBe` Nothing’
    In the expression:
      describe "safeHead"
      $ it "should return Nothing for empty list"
        $ safeHead [] `shouldBe` Nothing
Error:(26, 21) ghc: 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 (Maybe a) -- Defined in ‘GHC.Base’
      instance Eq a => Eq (GHC.Real.Ratio a) -- Defined in ‘GHC.Real’
      instance Eq Ordering -- Defined in ‘ghc-prim-0.4.0.0:GHC.Classes’
      ...plus 32 others
    In a stmt of a 'do' block: palindrome [] `shouldBe` []
    In the second argument of ‘($)’, namely
      ‘do { palindrome [] `shouldBe` [] }’
    In the second argument of ‘($)’, namely
      ‘it
         "should turn a list into a palindrome, so it reads same both forwards and backwards"
       $ do { palindrome [] `shouldBe` [] }’
我不知道这里有什么问题。如果我尝试其他类似的测试,它编译得很好:

    it "should return the head" $ do
      safeHead [1] `shouldBe` Just 1
      safeHead [2,3,4,5,6,1] `shouldBe` Just 2
所以,它是关于
本身的东西,不能用相等的东西来比较?那么,您如何断言某个东西返回
Nothing
?还是我的函数太泛化了

旁注: 我在这个函数中看到了类似的错误:

safeHead :: [a] -> Maybe a
safeHead [] = Nothing
safeHead (x:xs) = Just x
palindrome :: (Eq a) => [a] -> [a]
palindrome xs = xs ++ reverse xs
尝试测试空列表时:

palindrome [] `shouldBe` []
它失败于:

Error:(14, 19) ghc: 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 Eq Data.Monoid.All -- Defined in ‘Data.Monoid’
      instance forall (k :: BOX) (f :: k -> *) (a :: k).
               Eq (f a) =>
               Eq (Data.Monoid.Alt f a)
        -- Defined in ‘Data.Monoid’
      ...plus 43 others
    In the second argument of ‘($)’, namely
      ‘safeHead [] `shouldBe` Nothing’
    In the second argument of ‘($)’, namely
      ‘it "should return Nothing for empty list"
       $ safeHead [] `shouldBe` Nothing’
    In the expression:
      describe "safeHead"
      $ it "should return Nothing for empty list"
        $ safeHead [] `shouldBe` Nothing
Error:(26, 21) ghc: 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 (Maybe a) -- Defined in ‘GHC.Base’
      instance Eq a => Eq (GHC.Real.Ratio a) -- Defined in ‘GHC.Real’
      instance Eq Ordering -- Defined in ‘ghc-prim-0.4.0.0:GHC.Classes’
      ...plus 32 others
    In a stmt of a 'do' block: palindrome [] `shouldBe` []
    In the second argument of ‘($)’, namely
      ‘do { palindrome [] `shouldBe` [] }’
    In the second argument of ‘($)’, namely
      ‘it
         "should turn a list into a palindrome, so it reads same both forwards and backwards"
       $ do { palindrome [] `shouldBe` [] }’
所以,它本身就是一件无关紧要的事情,它不能用相等的东西来比较

什么是
Nothing
类型?它是
Nothing::可能是一个
。在这种情况下,GHC不喜欢
a
:“类型变量'a0'不明确”。毕竟,
应该是
获取任何可以与
(==)
进行比较并显示的内容。如果
a
Eq
的实例,那么
可能a
Eq
的实例。GHC不可能知道要使用哪个
a
,因此需要手动指定:

  describe "safeHead" $
    it "should return Nothing for empty list" $
      safeHead [] `shouldBe` (Nothing :: Maybe Int)
这不是强迫,你只是想弄清楚你想要使用哪种类型。其他例子:

  describe "safeHead" $
    it "should return Nothing for empty list" $ do
      safeHead [] `shouldBe` (Nothing :: Maybe Int)
      safeHead [] `shouldBe` (Nothing :: Maybe ())
      safeHead [] `shouldBe` (Nothing :: Maybe Integer)
      safeHead [] `shouldBe` (Nothing :: Maybe Char)

试试看
safeHead([]:[Int])
应该是“没用的”!这背后的原因是什么?您正在强制参数具有类型?像演员一样?@Zeta对此给出了一个非常好的回答,谢谢你的详细解释:)