如何快速检查应用同态 属性?

How to quickcheck applicative homomorphism property?

作为练习,我正在尝试快速检查应用程序的同态性 属性:

pure f <*> pure x = pure (f x)

当我尝试使用虚类型以一般方式编写 属性 时,我似乎 运行 陷入无穷无尽的 'Could not deduce' 错误。此时我已经在我的代码中添加了许多类型注释,但仍然出现这些错误。

我的代码是:

{-# LANGUAGE ViewPatterns #-}

import Test.QuickCheck (quickCheck)
import Test.QuickCheck.Function (Fun, apply)

-- | phantom type
data T a = T

-- | pure f <*> pure x = pure (f x)
prop_homomorphism :: (Applicative f, Eq b, Eq (f b)) => (T a) -> (T (f b)) -> Fun a b -> a -> Bool
prop_homomorphism T T (apply -> g) x = (pure (g :: a -> b) <*> pure x :: (Applicative f, Eq (f b)) => f b) == (pure (g x) :: (A
pplicative f, Eq (f b)) => f b)


prop_maybeint :: IO ()
prop_maybeint = do
  quickCheck (prop_homomorphism (T :: T Int) (T :: T (Maybe Int)))


main = do
  prop_maybeint

这给出的错误是:

applicativehomomorphism.hs:11:40: error:
    • Could not deduce (Eq (f0 b0)) arising from a use of ‘==’
      from the context: (Applicative f, Eq b, Eq (f b))
        bound by the type signature for:
                   prop_homomorphism :: (Applicative f, Eq b, Eq (f b)) =>
                                        T a -> T (f b) -> Fun a b -> a -> Bool
        at applicativehomomorphism.hs:10:1-98
      The type variables ‘f0’, ‘b0’ are ambiguous
      These potential instances exist:
        instance Eq a => Eq (Maybe a) -- Defined in ‘GHC.Base’
        instance (Eq a, Eq b) => Eq (a, b) -- Defined in ‘GHC.Classes’
        instance (Eq a, Eq b, Eq c) => Eq (a, b, c)
          -- Defined in ‘GHC.Classes’
        ...plus 13 others
        ...plus one instance involving out-of-scope types
        (use -fprint-potential-instances to see them all)
    • In the expression:
        (pure (g :: a -> b) <*> pure x :: (Applicative f, Eq (f b)) => f b)
        == (pure (g x) :: (Applicative f, Eq (f b)) => f b)
      In an equation for ‘prop_homomorphism’:
          prop_homomorphism T T (apply -> g) x
            = (pure (g :: a -> b) <*> pure x ::
                 (Applicative f, Eq (f b)) => f b)
              == (pure (g x) :: (Applicative f, Eq (f b)) => f b)

applicativehomomorphism.hs:11:41: error:
    • Could not deduce (Applicative f0)
        arising from an expression type signature
      from the context: (Applicative f, Eq b, Eq (f b))
        bound by the type signature for:
                   prop_homomorphism :: (Applicative f, Eq b, Eq (f b)) =>
                                        T a -> T (f b) -> Fun a b -> a -> Bool
        at applicativehomomorphism.hs:10:1-98
      The type variable ‘f0’ is ambiguous
      These potential instances exist:
        instance Applicative IO -- Defined in ‘GHC.Base’
        instance Applicative Maybe -- Defined in ‘GHC.Base’
        instance Applicative ((->) a) -- Defined in ‘GHC.Base’
        ...plus two others
        ...plus two instances involving out-of-scope types
        (use -fprint-potential-instances to see them all)
    • In the first argument of ‘(==)’, namely
        ‘(pure (g :: a -> b) <*> pure x ::
            (Applicative f, Eq (f b)) => f b)’
      In the expression:
        (pure (g :: a -> b) <*> pure x :: (Applicative f, Eq (f b)) => f b)
        == (pure (g x) :: (Applicative f, Eq (f b)) => f b)
      In an equation for ‘prop_homomorphism’:
          prop_homomorphism T T (apply -> g) x
            = (pure (g :: a -> b) <*> pure x ::
                 (Applicative f, Eq (f b)) => f b)
              == (pure (g x) :: (Applicative f, Eq (f b)) => f b)

applicativehomomorphism.hs:11:47: error:
    • Couldn't match type ‘b’ with ‘b2’
      ‘b’ is a rigid type variable bound by
        the type signature for:
          prop_homomorphism :: forall (f :: * -> *) b a.
                               (Applicative f, Eq b, Eq (f b)) =>
                               T a -> T (f b) -> Fun a b -> a -> Bool
        at applicativehomomorphism.hs:10:22
      ‘b2’ is a rigid type variable bound by
        an expression type signature:
          forall a1 b2. a1 -> b2
        at applicativehomomorphism.hs:11:52
      Expected type: a1 -> b2
        Actual type: a -> b
    • In the first argument of ‘pure’, namely ‘(g :: a -> b)’
      In the first argument of ‘(<*>)’, namely ‘pure (g :: a -> b)’
      In the first argument of ‘(==)’, namely
        ‘(pure (g :: a -> b) <*> pure x ::
            (Applicative f, Eq (f b)) => f b)’
    • Relevant bindings include
        g :: a -> b (bound at applicativehomomorphism.hs:11:33)
        prop_homomorphism :: T a -> T (f b) -> Fun a b -> a -> Bool
          (bound at applicativehomomorphism.hs:11:1)

applicativehomomorphism.hs:11:112: error:
    • Couldn't match type ‘b’ with ‘b1’
      ‘b’ is a rigid type variable bound by
        the type signature for:
          prop_homomorphism :: forall (f :: * -> *) b a.
                               (Applicative f, Eq b, Eq (f b)) =>
                               T a -> T (f b) -> Fun a b -> a -> Bool
        at applicativehomomorphism.hs:10:22
      ‘b1’ is a rigid type variable bound by
        an expression type signature:
          forall (f1 :: * -> *) b1. (Applicative f1, Eq (f1 b1)) => f1 b1
        at applicativehomomorphism.hs:11:126
      Expected type: f1 b1
        Actual type: f1 b
    • In the second argument of ‘(==)’, namely
        ‘(pure (g x) :: (Applicative f, Eq (f b)) => f b)’
      In the expression:
        (pure (g :: a -> b) <*> pure x :: (Applicative f, Eq (f b)) => f b)
        == (pure (g x) :: (Applicative f, Eq (f b)) => f b)
      In an equation for ‘prop_homomorphism’:
          prop_homomorphism T T (apply -> g) x
            = (pure (g :: a -> b) <*> pure x ::
                 (Applicative f, Eq (f b)) => f b)
              == (pure (g x) :: (Applicative f, Eq (f b)) => f b)
    • Relevant bindings include
        g :: a -> b (bound at applicativehomomorphism.hs:11:33)
        prop_homomorphism :: T a -> T (f b) -> Fun a b -> a -> Bool
          (bound at applicativehomomorphism.hs:11:1)

我已经为此苦苦挣扎了一段时间,而且很困惑。我的问题是什么?

luqui 的建议帮我解决了这个问题。

问题是我需要使用 ScopedTypeVariablesforall 以便在函数体的类型注释中引用其类型签名之外的类型参数。

我在 ScopedTypeVariables 上找到的一些相关资源: