Best way to implement ad-hoc polymorphism in Haskell?

后端 未结 3 1748
悲&欢浪女
悲&欢浪女 2020-12-28 09:32

I have a polymorphic function like:

convert :: (Show a) => a -> String
convert = \" [label=\" ++ (show a) ++ \"]\"

But sometimes I w

3条回答
  •  被撕碎了的回忆
    2020-12-28 09:50

    What you just explained is you want a function that behaves differently based on the type of the input. While you could use a data wrapper, thus closing the function for all time:

    data Convertable k a = ConvMap (Map k a) | ConvOther a
    convert (ConvMap m) = ...
    convert (ConvOther o) = ...
    

    A better way is to use type classes, thus leaving the convert function open and extensible while preventing users from inputting non-sensical combinations (ex: ConvOther M.empty).

    class (Show a) => Convertable a where
        convert :: a -> String
    
    instance Convertable (M.Map k a) where
        convert m = processMap2FancyKVString m
    
    newtype ConvWrapper a = CW a
    instance Convertable (ConvWrapper a) where
        convert (CW a) = " [label=" ++ (show a) ++ "]"
    

    In this manner you can have the instances you want used for each different data type and every time a new specialization is needed you can extend the definition of convert simply by adding another instance Convertable NewDataType where ....

    Some people might frown at the newtype wrapper and suggest an instance like:

    instance Convertable a where
        convert ...
    

    But this will require the strongly discouraged overlapping and undecidable instances extensions for very little programmer convenience.

提交回复
热议问题