我希望创建一个关联类型系列的两个实例,就像这样。当然,这不会编译,我最终在我的代码中采用了不同的方法。但是,我仍然对这个用例感到好奇。我认为理论上编译器可以允许这样做。即使可以选择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?,这与我的问题非常相似。但是,我的重点是努力更好地理解类型系统。
答案 0 :(得分:5)
类型族比MPTC弱一点,因为它们仅表示类型的函数而不是完整关系。这对于类型推断具有优势,也是MPTC也有趣的原因。因此,我不认为实现这样的事情是不可能的,但它却落后于类型检测器功率/重量比的错误。
无论如何,如果你真的想要这种行为,通过MPTC很容易
class Genetic s g where
-- | Writes a gene to a sequence.
put :: s -> g -> s
-- | Reads the next gene in a sequence.
get :: s -> (g, s)
instance Genetic [Bool] SampleGene where
put xs Variant1 = True : xs
put xs Variant2 = False : xs
get (True : xs) = (Variant1, xs)
get (False : xs) = (Variant2, xs)
instance Genetic [Int] SampleGene where
put xs Variant1 = 0 : xs
put xs Variant2 = 1 : xs
get (0 : xs) = (Variant1, xs)
get (1 : xs) = (Variant2, xs)
get _ = error "boo"