我希望創建一個關聯類型族的兩個實例,就像這樣。當然,這不會編譯,我最終在代碼中採用了不同的方法。不過,我仍然對這個用例感到好奇。我認爲理論上編譯器可以允許這樣做。即使有多個put
和get
的實例可供選擇,結果類型也會清除需要哪個實例。兩種不同方式的類型類的實例
{-# LANGUAGE TypeFamilies #-}
import Data.Word
class Genetic g where
type Sequence g :: *
-- | Writes a gene to a sequence.
put :: Sequence g -> g -> Sequence g
-- | Reads the next gene in a sequence.
get :: Sequence g -> (g, Sequence g)
data SampleGene = Variant1 | Variant2 deriving Show
instance Genetic SampleGene where
type Sequence SampleGene = [Bool]
put xs Variant1 = True : xs
put xs Variant2 = False : xs
get (True:xs) = (Variant1, xs)
get (False:xs) = (Variant2, xs)
instance Genetic SampleGene where
type Sequence SampleGene = [Word8]
put xs Variant1 = 0 : xs
put xs Variant2 = 1 : xs
get (0:xs) = (Variant1, xs)
get (1:xs) = (Variant2, xs)
get _ = error "coding error"
main = do
putStrLn "Working with Bool sequences"
let xs = put [] Variant1 :: [Bool]
let (g,ys) = get xs :: (SampleGene, [Bool])
putStrLn $ "Read " ++ show g
putStrLn "Working with Bool sequences"
let xs = put [] Variant1 :: [Word8]
let (g,ys) = get xs :: (SampleGene, [Word8])
putStrLn $ "Read " ++ show g
我的問題是:
有沒有辦法在Haskell做到這一點? (除了newtype包裝 - 我希望我的庫的用戶能夠直接使用Haskell基本類型。)
如果不是,爲什麼不呢?也就是說,我違反了什麼規則,或者我打了什麼類型系統的限制?我想在我正在寫的一篇論文中解釋這一點,但我試圖瞭解類型系統如何在隱藏條件下工作。因此,如果您在答案中使用技術術語,那麼我可以在閱讀中瞭解這些術語。
理論上,未來的Haskell擴展可能允許這樣做,還是它是非啓動器?
我看過In Haskell, is there any way to express that a type should be an instance of a typeclass in more than one way?,這與我的問題非常相似。但是,我的重點是試圖更好地理解類型系統。
我不是100%肯定,但我認爲即使有型的家庭,你會需要使用newtypes,這主要是'newtype'語義的用途,另一個用途是你可以使類型更明顯,比如使用'Network.Socket.PortNumber'而不是'Word16',使得類型簽名更加清晰至於這個論點需要什麼。 – bheklilr
您是否曾嘗試將「Sequence」的類型作爲第二個參數添加到類中? –
@Joachim我沒有嘗試多參數類型的類。這種趨勢似乎是使用類型家庭,但也許這是MPTC可以做某些類型家庭無法做到的事情。 – mhwombat