Fun with types! Resolving multiple instance declarations

前端 未结 2 1006
梦如初夏
梦如初夏 2020-12-20 23:06

I\'m trying to write some Haskell code in which there are multiple data types, each of which can have multiple implementations. To do this, I define each data type as a

相关标签:
2条回答
  • 2020-12-20 23:39

    There's no really good way to do this; the best practice is to define some constants like

    plusA, minusA :: (A a, Num x) => a x -> a x -> a x
    

    which makes writing the Num instances more mechanical after you have an A instance:

    instance A Foo where ...
    instance Num x => Num (Foo x) where
        (+) = plusA
        (-) = minusA
    
    0 讨论(0)
  • 2020-12-20 23:50

    This part of your question

    I suppose that the 'duplicate instance declarations' message is because a data type could be made an instance of both A and B. I want to be able to make a promise to the compiler that I won't do that, or possibly specify a default class to use in the case that a type is an instance of both classes.

    is incorrect. It's actually because you've written two instances,

    instance Num (a x)
    instance Num (b x)
    

    that the compiler can't tell apart (see the link from @hammar's comment, class contexts don't count for the purpose of differentiating between instance declarations).

    One solution is to add a witness type.

    {-# LANGUAGE FlexibleInstances, FlexibleContexts, UndecidableInstances, OverlappingInstances #-}
    
    data AWitness
    
    data AImpl witness x = AImpl x deriving (Eq,Show)
    
    instance A (AImpl AWitness) where
        fa (AImpl x) = x
        ga x = AImpl x
    
    instance (A (a AWitness), Num x, Show (a AWitness x), Eq (a AWitness x)) => Num (a AWitness x) where
        a1 + a2 = ga (fa a1 + fa a2)
    

    The compiler can use the witness types to differentiate between your instance declarations.

    0 讨论(0)
提交回复
热议问题