[英]How to constrain associated type synonyms?
我(相對)是 Haskell 的新手,想編寫一些數學代碼。 例如,阿貝爾群。 我想編寫以下代碼:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeFamilyDependencies #-}
module Structures where
class Eq g => AbelianGroup g where
type family AbelianGroupElement g = e | e -> g
add :: AbelianGroupElement g -> AbelianGroupElement g -> AbelianGroupElement g
inv :: AbelianGroupElement g -> AbelianGroupElement g
unit :: g -> AbelianGroupElement g
parent :: AbelianGroupElement g -> g
data Z = Z deriving Eq
data ZElement = ZElement Z Int deriving Eq
instance AbelianGroup Z where
type instance AbelianGroupElement Z = ZElement
add (ZElement z1 x1) (ZElement z2 x2)
| z1 == z2 = (ZElement z1 (x1+x2))
| otherwise = error "elements from different groups"
inv (ZElement z x) = (ZElement z (-x))
unit z = ZElement z 0
parent (ZElement z x) = z
data ProductAbGrp g1 g2 =
ProductAbGrp g1 g2 deriving Eq
data ProductAbGrpEl g1 g2 =
ProductAbGrpEl (ProductAbGrp g1 g2) (AbelianGroupElement g1) (AbelianGroupElement g2) deriving Eq
編譯上面給我的錯誤
No instance for (Eq (AbelianGroupElement g1))
arising from the second field of `ProductAbGrpEl'
(type `AbelianGroupElement g1')
這是有道理的; 我沒有確保 (AbelianGroupElement g1) 總是為它定義了 Eq。 但是,我不確定如何實現這一點。 我可以將以上內容更改為
{-# LANGUAGE FlexibleContexts #-}
...
class (Eq g, Eq (AbelianGroupElement g)) => AbelianGroup g where
但這無濟於事。 (這里的類型族可能是 go 的錯誤方式;我最初是從 MultiParamTypeClasses 和 FunctionalDependencies 開始的,但有其他問題,並且給人的印象是類型族更好)。
感謝您閱讀本文; 任何幫助,將不勝感激。
您可以使用StandaloneDeriving
基本上得到您想要的,盡管我承認它不像簡單地編寫deriving Eq
那樣漂亮:
{-# LANGUAGE StandaloneDeriving #-}
deriving instance (Eq g1, Eq g2, Eq (AbelianGroupElement g1), Eq (AbelianGroupElement g2)) => Eq (ProductAbGrpEl g1 g2)
我最終切換到 MultiParamTypeClasses 和 FunctionalDependencies 方法。 我不確定這是否是最好的做事方式,但它至少解決了這個問題。 我以前試過這個,但不知道我可以同時添加依賴項e -> g
和g -> e
,這在編譯這段代碼方面有所不同。
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
module Structures where
class (Eq g, Show g, Eq e, Show e) => AbelianGroup g e | e -> g, g -> e where
zero :: g -> e
add :: e -> e -> e
neg :: e -> e
parent :: e -> g
data Z = Z deriving (Eq, Show)
data ZElement = ZElement Z Int deriving (Eq, Show)
instance AbelianGroup Z ZElement where
zero z = ZElement z 0
add (ZElement z1 x1) (ZElement z2 x2)
| z1 == z2 = (ZElement z1 (x1+x2))
| otherwise = error "elements from different groups"
neg (ZElement z x) = (ZElement z (-x))
parent (ZElement z x) = z
data ProductAbelianGroup g1 g2 e1 e2 = ProductAbelianGroup g1 g2 deriving (Eq, Show)
data ProductAbelianGroupElement g1 g2 e1 e2 = ProductAbelianGroupElement g1 g2 e1 e2 deriving (Eq, Show)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.