2016-04-15 60 views
0

我嘗試瞭解如何使用數據類型族來隱藏構造函數。給出的微不足道的例子是一對具有從普通對轉換成普通對的操作等)。 bifunctor的實例不能編譯;該錯誤信息是類型族:如何爲一對數據類型族實例化Bifunctor?

src/TypeFamilyTest.hs:66:21: 的Bifunctor的第一個參數應該有一種* -> * -> *, 但Pairs a b有種ghc-prim-0.4.0.0:GHC.Prim.Constraint

在實例聲明Bifunctor (Pairs a b)

試圖Bifunctor Pair where ...我再弄錯誤消息列表相同GHC.Prim.Constraint。該實例的正確參數是什麼?上下文將如何傳遞?

class Pairs a b where 
    data Vec2 a b 

    mkPair :: (a,b) -> Vec2 a b -- (FirstF a, SecondF a) -> a 
    splitPair :: Vec2 a b -> (a,b) 
    fstP :: Vec2 a b -> a 
    sndP :: Vec2 a b -> b 
    fstP = fst . splitPair 
    sndP = snd . splitPair 

instance () => Bifunctor (Pairs a b) where 
    bimap opv oph vh = mkPair (opv . fstP $ vh, oph . sndP $ vh) 
+3

數據家族並不是隱藏構造函數。它們的構造函數可以以普通數據類型的相同方式顯示或隱藏。數據族關於非參數數據類型 - 在決定其構造函數的外觀之前檢查其類型參數的類型。 –

+1

類型類不是面向對象意義上的類。它不封裝數據和操作它的操作。 – chepner

+0

Haskell'class'最接近OOP的概念是類似Java的'interface',即使這種對應也是鬆散的。 – chi

回答

2

類型錯誤告訴你一切。 Pair不是數據類型的名稱。這是一個班的名字。 Pair a b :: Constraint so Pair :: * -> * -> ConstraintBifunctor只能通過種類* -> * -> *的數據類型實例化。

我猜你的意思是不是這樣的事情:

newtype Pair a b = Vec2 { splitPair :: (a, b) } 

fstP :: Pair a b -> a 
fstP = fst . splitPair 

sndP :: Pair a b -> b 
sndP = snd . splitPair 

instance Bifunctor Pair where 
    bimap f g (Vec2 (x, y)) = Vec2 (f x, g y) 

我不明白爲什麼你原先作出Vec2相應的類型。我懷疑這可能是一個XY problem - 你真的想達到什麼目的?

+2

看起來OP正試圖模擬面向對象的編程,'Pairs'是封裝了'Vec2'的類型。這是巧合的,他們的嘗試在語法上是正確的。 – chepner

+0

我欣賞有用的答案。我試圖減少一個程序中的混亂,我覺得我有太多的類,並開始與相關類型的實驗。我現在瞭解得更清楚,哪些關聯類型對於建議的線路有用並將使用解決方案。 - 謝謝! – user855443