簡體   English   中英

如何約束關聯類型同義詞?

[英]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 -> gg -> 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM