首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >QuickCheck属性的干式注释

QuickCheck属性的干式注释
EN

Stack Overflow用户
提问于 2018-10-03 12:57:03
回答 1查看 237关注 0票数 2

使用QuickCheck,可以编写参数多态属性,如下所示:

代码语言:javascript
复制
associativityLaw :: (Eq a, Show a, Semigroup a) => a -> a -> a -> Property
associativityLaw x y z = (x <> y) <> z === x <> (y <> z)

这只是一个例子,因为我的实际属性更复杂,但它充分说明了这个问题。此属性验证对于类型a<>运算符是否是关联的。

想象一下,我想要使用这个属性超过一种类型。我可以这样定义我的测试列表:

代码语言:javascript
复制
tests =
  [
    testGroup "Monoid laws" [
      testProperty "Associativity law, [Int]" (associativityLaw :: [Int] -> [Int] -> [Int] -> Property),
      testProperty "Associativity law, Sum Int" (associativityLaw :: Sum Int -> Sum Int -> Sum Int -> Property)
    ]
  ]

这是可行的,但觉得不必要的冗长。我希望能够简单地声明,对于给定的属性,a应该是[Int],或者a应该是Sum Int

类似于假设的语法:

代码语言:javascript
复制
testProperty "Associativity law, [Int]" (associativityLaw :: a = [Int]),
testProperty "Associativity law, Sum Int" (associativityLaw :: a = Sum Int)

有没有办法做到这一点,也许通过一个GHC语言扩展?

我的实际问题涉及类型较高的类型,我希望能够说明,例如,f a[Int]f aMaybe String

我知道this answer,但这两种选项(ProxyTagged)看起来,至少在这里描述过,太尴尬了,以至于无法真正解决这个问题。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-10-03 13:11:51

您可以使用TypeApplications绑定类型变量,如下所示:

代码语言:javascript
复制
{-# LANGUAGE TypeApplications #-}

associativityLaw @[Int]

在您提到的具有较高类型并希望将f a绑定到[Int]的情况下,必须分别绑定类型变量fa

代码语言:javascript
复制
fmap @[] @Int

对于具有多个类型变量的函数,可以按顺序应用args:

代码语言:javascript
复制
f :: a -> b -> Int

-- bind both type vars    
f @Int @String

-- bind just the first type var, and let GHC infer the second one
f @Int

-- bind just the second type var, and let GHC infer the first one
f @_ @String

有时,类型变量的“顺序”可能并不明显,但您可以使用:type +v并向GHCi查询更多信息:

代码语言:javascript
复制
λ> :t +v traverse
traverse
  :: Traversable t =>
     forall (f :: * -> *) a b.
     Applicative f =>
     (a -> f b) -> t a -> f (t b)

在标准haskell中,类型变量的“顺序”并不重要,所以GHC只是为您提供一个。但在TypeApplications在场的情况下,这个命令确实很重要:

代码语言:javascript
复制
map :: forall b a. (a -> b) -> ([a] -> [b])
-- is not the same as
map :: forall a b. (a -> b) -> ([a] -> [b])

因此,当您使用高度参数化的代码时,或者您希望您的用户希望在您的函数上使用TypeApplications时,您可能希望显式地设置您的类型vars的顺序,而不是让GHC使用ExplicitForAll为您定义一个订单。

代码语言:javascript
复制
{-# LANGUAGE ExplicitForAll #-}

map :: forall a b. (a -> b) -> ([a] -> [b])

这感觉很像java或c#中的c#。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52627561

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档