Haskell: Instance definitions for type families

后端 未结 2 1982
余生分开走
余生分开走 2021-01-22 10:53

Lets say we have the following code:

class C t where
  g :: t

instance C Int where
  g = 42

Simple. We can also define functions on Int, like

相关标签:
2条回答
  • 2021-01-22 11:27

    The following file compiles here:

    {-# LANGUAGE GeneralizedNewtypeDeriving, TypeFamilies #-}
    
    class C a where g :: a
    type family X
    type instance X = Int
    newtype NewX = NewX X deriving Num
    instance C NewX where g = 43
    
    0 讨论(0)
  • 2021-01-22 11:38

    A newtype does just that--it defines a new type, while a type defines a synonym. If you dont like a bunch of deriving clauses, one can always use the isomorphism with the underlying type

    instance C NewX where
       g = NewX  43
    

    the reason type synonyms dont play nice with Instance declarations, is that functions (including type functions) only work in one direction. You can only pattern match on constructors, so newtype allows you to introduce a new type constructor at zero runtime cost. In your problem, why not

    newtype Row = Row {runRow :: FieldOf Col1 :&: FieldOf Col2}
    
    instance Indexable Row where
      empty = ixSet [ixFun $ (\x -> [ Col1 ^. (runRow x) ]) ]
    

    I should note that in general GeneralizedNewtypeDeriving is unsound. Doesn't mean you should avoid using it, but does imply what you want is probably impossible.


    Edit (Question asker):

    Better yet, no need to even change the data type Row

    newtype Row = Row ( FieldOf Col1 :&: FieldOf Col2 )
    
    instance Indexable Row where
      empty = ixSet [ixFun $ (\(Row x) -> [ Col1 ^. x ]) ]
    
    0 讨论(0)
提交回复
热议问题