这个问题与我的other question about smallCheck的Test.SmallCheck.Series类有关。当我试图以以下自然方式定义类Serial的实例时(通过@tel对上述问题的回答向我建议),我会得到编译器错误:
data Person = SnowWhite | Dwarf Int
instance Serial Person where ...事实证明,Serial想要有两个论点。这反过来又需要一些编译器标志。以下工作:
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
import Test.SmallCheck
import Test.SmallCheck.Series
import Control.Monad.Identity
data Person = SnowWhite | Dwarf Int
instance Serial Identity Person where
series = generate (\d -> SnowWhite : take (d-1) (map Dwarf [1..7]))我的问题是:
Identity放在那里是“正确的事情”吗?Test.Series.list函数的类型给了我灵感(当我第一次看到它的时候,我也发现了非常奇怪的地方):
列表:深度->系列标识a -> a
怎么做才是对的呢?当我看到Identity时,如果我盲目地把它放进去,我会没事吗?我应该放一些类似Serial m Integer => Serial m Person的东西(这至少需要一些看起来更吓人的编译器标志:FlexibleContexts和UndecidableInstances )?m in Serial m n)用于什么?
谢谢!发布于 2013-05-15 08:21:57
我只是一个小检查的用户,而不是一个开发人员,但我认为答案是
1)不完全是。您应该保留它的多态性,可以不使用上述扩展:
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
import Test.SmallCheck
import Test.SmallCheck.Series
import Control.Monad.Identity
data Person = SnowWhite | Dwarf Int deriving (Show)
instance (Monad m) => Serial m Person where
series = generate (\d -> SnowWhite : take (d-1) (map Dwarf [1..7]))2)系列目前被定义为
newtype Series m a = Series (ReaderT Depth (LogicT m) a)这意味着m是LogicT的基本单元,用于生成系列中的值。例如,编写IO代替m将允许IO操作在生成系列时发生。
在SmallCheck中,m也出现在Testable实例声明(如instance (Serial m a, Show a, Testable m b) => Testable m (a->b) )中。这样做的具体效果是,如果只有smallCheck :: Testable IO a => Depth -> a -> IO ()的实例,就不能使用现有的驱动程序函数(如Identity )。
在实践中,您可以通过编写一个自定义驱动程序函数来利用这一事实,该函数交织了一些一元效应,例如在所述驱动程序中记录生成的值(或类似的值)。
它也可能是有用的其他事情,我不知道。
https://stackoverflow.com/questions/16557610
复制相似问题