[英]How to write `Semigroup` instance and their `quickCheck`s on parameterized types?
In the exercises of Haskell Programming from First Principle book on Semigroup, I am asked to write quickCheck
for user defined typeclasses. 在Semigroup的《第一原理》一书中的Haskell编程练习中,要求我为用户定义的类型类编写
quickCheck
。 There are many typeclasses, but I do not understand how to write even the basic ones: 有很多类型类,但是我什至不了解如何编写基本类:
The first is for Trivial
: 第一个是
Trivial
:
module Exercise where
import Test.QuickCheck
data Trivial =
Trivial
deriving (Eq, Show)
instance Semigroup Trivial where
_ <> _ = undefined
instance Arbitrary Trivial where
arbitrary = return Trivial
semigroupAssoc :: (Eq m, Semigroup m) => m -> m -> m -> Bool
semigroupAssoc a b c = (a <> (b <> c)) == ((a <> b) <> c)
type TrivialAssoc = Trivial -> Trivial -> Trivial -> Bool
The second is for 第二个是
newtype Identity a = Identity a
and the third is for: 第三是:
data Two a b =
Two a b
For the first, I changed the instance
expression to 首先,我将
instance
表达式更改为
instance Semigroup Trivial where
_ <> _ = Trivial
and it works. 而且有效。
I tried the following code but not work for the second: 我尝试了以下代码,但第二步不起作用:
newtype Identity a = Identity a
instance (Semigroup a) => Semigroup (Identity a) where
(Identity a1) <> (Identity a2) = Identity (a1 <> a2)
instance Arbitrary (Identity a) where
arbitrary = return (Identity a)
type IdentityAssoc =
(Identity a0) -> (Identity a1) -> (Identity a2) -> Bool
main :: IO ()
main =
quickCheck (semigroupAssoc :: IdentityAssoc)
I find I do not understand what the quickTest
should check here. 我发现我不明白
quickTest
应该在这里检查什么。 I even tried: 我什至尝试:
import Data.NonEmpty
newtype Identity a = Identity a
instance (Semigroup a) => Semigroup (Identity a) where
(Identity a1) <> (Identity a2) = Identity (a1 <> a2)
instance Arbitrary (Identity a) where
arbitrary = return (Identity a)
type IdentityAssoc =
(Identity (NonEmpty Int)) -> (Identity (NonEmpty Int)) -> (Identity (NonEmpty Int)) -> Bool
main :: IO ()
main =
quickCheck (semigroupAssoc :: IdentityAssoc)
to make the parameterized types' parameters concrete. 使参数化类型的参数具体化。 But it does not work either.
但这也不起作用。
For the third, I do not know how to write them. 第三,我不知道该怎么写。 But I think it is similar to the second one.
但我认为它类似于第二个。
Can someone explain on these so that I can understand how to write the instance
of parameterized Semigroups and their quickTest
arbitrary? 有人可以对此进行解释,以便我了解如何编写参数化
quickTest
instance
及其quickTest
任意对象吗?
This is wrong: 这是错误的:
instance Arbitrary (Identity a) where
arbitrary = return (Identity a)
a
is not a value variable, it is a type variable. a
不是值变量,而是类型变量。 We need a value of type a
to pass to the Identity
constructor, not the a
type itself. 我们需要类型的值,
a
传递给Identity
构造函数,而不是a
类型本身。
So we need something like 所以我们需要像
instance Arbitrary a => Arbitrary (Identity a) where
arbitrary = do
x <- arbitrary -- generate a value of type a
return (Identity x) -- turn it into a value of type (Identity a)
(or, more concisely, arbitrary = Identity <$> arbitrary
) (或更简洁地说,
arbitrary = Identity <$> arbitrary
)
Note how we have to require that a
is a type for which we can generate random samples (adding Arbitrary a =>
after Instance
). 请注意,我们必须如何要求
a
是我们可以为其生成随机样本的类型(在Instance
之后添加Arbitrary a =>
)。 Otherwise, we can't use x <- arbitrary
to generate a sample for a
. 否则,我们不能使用
x <- arbitrary
为a
生成样本。
Further: 进一步:
type IdentityAssoc =
(Identity a0) -> (Identity a1) -> (Identity a2) -> Bool
Here we can't refer to a1,a1,a2
, since we haven't defined those types anywhere. 这里我们不能引用
a1,a1,a2
,因为我们还没有在任何地方定义这些类型。 We need to choose concrete types, like Int
. 我们需要选择具体类型,例如
Int
。 Further, these three types must be the same type, since (<>)
takes two values of the same type, and returns a value in that type. 此外,这三种类型必须是同一类型,因为
(<>)
接受两个相同类型的值,并返回该类型的值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.