2013-05-15 47 views
3

這個問題與我的other question有關smallCheckTest.SmallCheck.Series類。當我嘗試在以下自然的方式(通過@tel上述問題的答案建議我)來定義類Serial的一個實例,我得到的編譯器錯誤:爲什麼smallCheck的`Series`類在構造函數中有兩種類型?

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])) 

我的問題是:

  1. 是把該Identity有 「做正確的事」?

    list :: Depth -> Series Identity a -> [a] 
    

    什麼是正確的事情:我被Test.Series.list函數的類型(我也發現非常奇怪的,當我第一次看到它)的啓發?如果我一看到Identity就會盲目放入,我會沒事的嗎?我應該把類似Serial m Integer => Serial m Person的東西,(至少需要一些更可怕的編譯器標誌:FlexibleContextsUndecidableInstances)?

  2. 什麼是第一個參數(mSerial m n)?

    謝謝!

回答

4

我只是smallcheck的用戶,而不是開發者,但我認爲答案是

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) 

這意味着mLogicT基礎單子它是用來生成系列中的值。例如,編寫IO代替m將允許在生成系列時發生IO操作。

在SmallCheck中,m也出現在Testable實例聲明中,如instance (Serial m a, Show a, Testable m b) => Testable m (a->b)。這具有以下具體效果:如果您只有Identity的實例,則不能使用smallCheck :: Testable IO a => Depth -> a -> IO()之前的驅動程序功能。

實際上,您可以通過編寫一個自定義驅動程序功能來使用這個事實,該驅動程序功能可以交織一些單一效果,例如在所述驅動程序內記錄生成的值(或其他)。

它也可能對我不知道的其他事情有用。

+0

非常感謝您給出了一個很好的答案和解釋!你的例子工作,它應該真的在文檔中。雖然,我必須承認,我很生氣,我必須明白'Series(ReaderT Depth(LogicT m)a)'意味着僅僅爲了一個具體目的而使用一個庫。 –

+1

你並不需要關心'LogicT'使用smallcheck。 – aleator

+0

好吧,也許我不需要*更多*的細節。但是,正因爲如此,我永遠無法猜測我應該怎麼做才能讓我的代碼在沒有您的幫助的情況下工作。 –

相關問題