Haskell 类型构造函数作为表达式的参数

Haskell 类型构造函数作为表达式的参数,haskell,Haskell,我使用hspec和QuickCheck来验证函子实例的函子定律。我有很多功能 functorIdentity :: (Functor f, Eq (f a)) => f a -> Bool 及 然后我将使用如下代码块测试这两个: testListFunctorness :: IO () testListFunctorness = hspec $ do describe "list" $ do it "should obey functor identity"

我使用hspec和QuickCheck来验证函子实例的函子定律。我有很多功能

functorIdentity :: (Functor f, Eq (f a)) => f a -> Bool

然后我将使用如下代码块测试这两个:

testListFunctorness :: IO ()
testListFunctorness =
  hspec $ do
    describe "list" $ do
      it "should obey functor identity" $ do
        property (functorIdentity :: [Int] -> Bool)
      it "should obey functor composition" $ do
        property
          (functorComposition :: (Fun Int String) -> (Fun String Int) -> [Int] -> Bool)
问题是,要为不同的Functor实例测试相同的属性,我需要复制除
[Int]
s以外的所有内容:

testMaybeFunctorness :: IO ()
testMaybeFunctorness =
  hspec $ do
    describe "maybe" $ do
      it "should obey functor identity" $ do
        property (functorIdentity :: Maybe Int -> Bool)
      it "should obey functor composition" $ do
        property
          (functorComposition :: (Fun Int String) -> (Fun String Int) -> Maybe Int -> Bool)
我觉得我应该能够编写一个表达式,它在不同的
Functor
实例上以某种方式是多态的,但我甚至不知道如何开始


如何方便地为多个不同的
Functor
重用该测试逻辑块?

您可以做的是显式地将所需类型传递给
testFunctorness

import Data.Proxy
testFunctorness::对于所有a。函子a=>代理a->IO()
测试函数性=
hspec$do
描述“类型”$do
它“应该服从函子标识”$do
属性(functionIdentity::a Int->Bool)
它“应该服从函子组合”$do
财产
(functorComposition::(趣味字符串)->(趣味字符串)->a Int->Bool)
调用看起来像
testFunctorness(Proxy::Proxy[])


您需要启用
{-#语言范围的TypeVariables#-}
,以便函数中的
a
引用类型签名中的
a
。然后需要所有的
forall
让类型检查器知道
a
应该是词汇范围。

我99%确定这里有AB问题,但我看不出B是什么:)啊,数据。代理很好。我在约束中使用了
任意(一个Int)、Show(一个Int)、Eq(一个Int)
来进行快速检查,但除此之外,它是完美的。
testMaybeFunctorness :: IO ()
testMaybeFunctorness =
  hspec $ do
    describe "maybe" $ do
      it "should obey functor identity" $ do
        property (functorIdentity :: Maybe Int -> Bool)
      it "should obey functor composition" $ do
        property
          (functorComposition :: (Fun Int String) -> (Fun String Int) -> Maybe Int -> Bool)