[英]How to write `Semigroup` instance and their `quickCheck`s on parameterized types?
在Semigroup的《第一原理》一書中的Haskell編程練習中,要求我為用戶定義的類型類編寫quickCheck
。 有很多類型類,但是我什至不了解如何編寫基本類:
第一個是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
第二個是
newtype Identity a = Identity a
第三是:
data Two a b =
Two a b
首先,我將instance
表達式更改為
instance Semigroup Trivial where
_ <> _ = Trivial
而且有效。
我嘗試了以下代碼,但第二步不起作用:
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)
我發現我不明白quickTest
應該在這里檢查什么。 我什至嘗試:
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)
使參數化類型的參數具體化。 但這也不起作用。
第三,我不知道該怎么寫。 但我認為它類似於第二個。
有人可以對此進行解釋,以便我了解如何編寫參數化quickTest
instance
及其quickTest
任意對象嗎?
這是錯誤的:
instance Arbitrary (Identity a) where
arbitrary = return (Identity a)
a
不是值變量,而是類型變量。 我們需要類型的值, a
傳遞給Identity
構造函數,而不是a
類型本身。
所以我們需要像
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)
(或更簡潔地說, arbitrary = Identity <$> arbitrary
)
請注意,我們必須如何要求a
是我們可以為其生成隨機樣本的類型(在Instance
之后添加Arbitrary a =>
)。 否則,我們不能使用x <- arbitrary
為a
生成樣本。
進一步:
type IdentityAssoc =
(Identity a0) -> (Identity a1) -> (Identity a2) -> Bool
這里我們不能引用a1,a1,a2
,因為我們還沒有在任何地方定義這些類型。 我們需要選擇具體類型,例如Int
。 此外,這三種類型必須是同一類型,因為(<>)
接受兩個相同類型的值,並返回該類型的值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.