gpt4 book ai didi

haskell - 如何使用检查器测试此应用实例? (没有 CoArbitrary 实例(验证 e0 [Char]))

转载 作者:行者123 更新时间:2023-12-02 16:44:52 25 4
gpt4 key购买 nike

Checkers is a library for reusable QuickCheck properties, particularly for standard type classes

如何编写一个检查器实例来测试我的 Validation 应用实例是否有效?

import Test.QuickCheck
import Test.QuickCheck.Checkers
import Test.QuickCheck.Classes
import Control.Applicative
import Data.Monoid

data Validation e a =
Error e
| Scss a
deriving (Eq, Show)

instance Functor (Validation e) where
fmap _ (Error e) = Error e
fmap f (Scss a) = Scss $ f a

instance Monoid e => Applicative (Validation e) where
pure = Scss
(<*>) (Scss f) (Scss a) = Scss $ f a
(<*>) (Error g) (Scss a) = Error g
(<*>) (Scss a) (Error g) = Error g
(<*>) (Error a) (Error g) = Error $ mappend a g

instance (Arbitrary a, Arbitrary b) => Arbitrary (Validation a b) where
arbitrary = do
a <- arbitrary
b <- arbitrary
elements [Scss a, Error b]

instance (Eq a, Eq b) => EqProp (Validation a b) where (=-=) = eq

main :: IO ()
main = quickBatch $ applicative [(Scss "b", Scss "a", Scss "c")]

我想我已经快到了,但我收到一个错误,如下所示:

chap17/Validation_applicative.hs:36:21: No instance for (CoArbitrary (Validation e0 [Char])) …
arising from a use of ‘applicative’
In the second argument of ‘($)’, namely
‘applicative [(Scss "b", Scss "a", Scss "c")]’
In the expression:
quickBatch $ applicative [(Scss "b", Scss "a", Scss "c")]
In an equation for ‘main’:
main = quickBatch $ applicative [(Scss "b", Scss "a", Scss "c")]
Compilation failed.

我尝试添加 CoArbitrary 实例进行验证,如下所示:

instance CoArbitrary (Validation a b)

但这会导致此错误消息:

chap17/Validation_applicative.hs:35:10: No instance for (GHC.Generics.Generic (Validation a b)) …
arising from a use of ‘Test.QuickCheck.Arbitrary.$gdmcoarbitrary’
In the expression: Test.QuickCheck.Arbitrary.$gdmcoarbitrary
In an equation for ‘coarbitrary’:
coarbitrary = Test.QuickCheck.Arbitrary.$gdmcoarbitrary
In the instance declaration for ‘CoArbitrary (Validation a b)’
chap17/Validation_applicative.hs:38:21: No instance for (Eq e0) arising from a use of ‘applicative’ …
The type variable ‘e0’ is ambiguous
Note: there are several potential instances:
instance Eq a => Eq (Const a b) -- Defined in ‘Control.Applicative’
instance Eq a => Eq (ZipList a) -- Defined in ‘Control.Applicative’
instance Eq a => Eq (Data.Complex.Complex a)
-- Defined in ‘Data.Complex’
...plus 65 others
In the second argument of ‘($)’, namely
‘applicative [(Scss "b", Scss "a", Scss "c")]’
In the expression:
quickBatch $ applicative [(Scss "b", Scss "a", Scss "c")]
In an equation for ‘main’:
main = quickBatch $ applicative [(Scss "b", Scss "a", Scss "c")]
Compilation failed.

最佳答案

如何

要自动派生 CoArbitrary 实例,您的数据类型应该有一个 Generic 实例,它又可以通过一些不错的语言扩展自动派生:

{-# LANGUAGE DeriveGeneric #-}

import GHC.Generics

data Validation e a =
Error e
| Scss a
deriving (Eq, Show, Generic)

但是,您的程序中最严重的错误是您正在针对 [] 进行测试,而不是通过 applicative [(Scss "b", Scss "a", Scss "c “)]。这是 applicative 测试包的定义,详细信息省略:

applicative :: forall m a b c.
( Applicative m
, Arbitrary a, CoArbitrary a, Arbitrary b, Arbitrary (m a)
, Arbitrary (m (b -> c)), Show (m (b -> c))
, Arbitrary (m (a -> b)), Show (m (a -> b))
, Show a, Show (m a)
, EqProp (m a), EqProp (m b), EqProp (m c)
) =>
m (a,b,c) -> TestBatch
applicative = const ( "applicative"
, [ ("identity" , property identityP)
, ("composition" , property compositionP)
, ("homomorphism", property homomorphismP)
, ("interchange" , property interchangeP)
, ("functor" , property functorP)
]
)

简而言之,给定四种类型 mabc,此函数将创建一个m 作为应用仿函数应该满足的一堆属性,稍后您可以使用随机 a b 来测试它们cQuickCheck 生成的值。 [(Scss "b", Scss "a", Scss "c")] 具有类型 [(Validation String, Validation String, Validation String)] 使得 m~[].

因此,您应该提供一些 Validation e (a, b, c) 类型的值,或者根本不提供任何值:您可能已经注意到了 const 就在那里applicative 的定义,只有参数的类型很重要:

main :: IO ()
main = quickBatch $ applicative (undefined :: Validation String (Int, Double, Char))

之后您可以运行测试并获得格式正确的结果。但是不,您不应该以这种方式测试应用程序。

<小时/>

为什么不应该

checkers 提供的测试还远远不够。根据 GHC 的运行时单态性质及其处理歧义的方式,您必须提供四种具体的非多态类型来运行测试,例如 Validation String (Int, Double, Char) 和测试模块将仅生成并测试这四种类型,而您的应用仿函数应该适用于满足上下文的任何类型。

IMO 大多数多态函数都不太适合单元测试框架:它无法针对所有可能的类型进行测试,因此必须选择要么仅使用手动选择的类型进行一些测试,要么在足够通用的类型(例如当您的代码需要任意 monad 时使用 Free monad,但通常“足够通用”在其他上下文中没有明确定义)。

您最好严格检查您的实现,并证明所有情况下都满足所有法律,无论是用纸笔还是用 agda 等证明引擎。以下是也许的示例,可能会有所帮助:Proving Composition Law for Maybe Applicative

<小时/>

编辑:请阅读评论。我并不完全理解它,但这意味着 Integer 是用于单元测试多态函数的“足够通用”的类型。我发现This blog article by Bartosz Milewski及其引用书目是掌握参数性和自由定理思想的良好资源。

关于haskell - 如何使用检查器测试此应用实例? (没有 CoArbitrary 实例(验证 e0 [Char])),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36009335/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com