Generic conversion type class

I would like to see if it is possible to have a type class to convert one thing to another and vice versa from a mapping [(a,b)].

This example should show what I would like to do:

data XX = One | Two | Three deriving (Show, Eq)
data YY = Eno | Owt | Eerht deriving (Show, Eq)

instance Convert XX YY where
   mapping = [(One, Eno), (Two, Owt), (Three, Eerht)]

-- // How can I make this work?:
main = do print $ (convert One :: YY) -- Want to output: Eno
          print $ (convert Owt :: XX) -- Want to output: Two

Here is my kick for doing this job:

{-# LANGUAGE MultiParamTypeClasses #-}    
import Data.Maybe(fromJust)

lk = flip lookup
flipPair = uncurry $ flip (,)

class (Eq a, Eq b) => Convert a b where

   mapping :: [(a, b)]
   mapping = error "No mapping defined"

   convert :: a -> b
   convert = fromJust . lk mapping

-- // This won't work:
instance (Convert a b) => Convert b a where
   convert = fromJust . lk (map flipPair mapping)

This is easy to do with defining two instances for conversion anyway, but I would only like to declare it as in the first example. Any idea how I can do this?


Edit: if possible, I mean, can this be done without overlapping instances of any other nasty extensions?

+5
source share
1 answer

I, uh ... I hardly recommend it because doing it is monstrous, but ... does your code not work?

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE OverlappingInstances #-}
import Data.Maybe(fromJust)

lk x = flip lookup x
flipPair = uncurry $ flip (,)

class (Eq a, Eq b) => Convert a b where
   mapping :: [(a, b)]
   mapping = error "No mapping defined"
   convert :: a -> b
   convert = fromJust . lk mapping

instance (Convert a b) => Convert b a where
   convert = fromJust . lk (map flipPair mapping)

data XX = One | Two | Three deriving (Show, Eq)
data YY = Eno | Owt | Eerht deriving (Show, Eq)

instance Convert XX YY where
   mapping = [(One, Eno), (Two, Owt), (Three, Eerht)]

main = do print $ (convert One :: YY)
          print $ (convert Owt :: XX)

and

[1 of 1] Compiling Main             ( GeneralConversion.hs, interpreted )
Ok, modules loaded: Main.
*Main> main
Eno
Two
*Main> 

, , , , , . , - ... Convert a a (Convert a b, Convert b c) => Convert a c... .


, , :

  • , ; , . , , fromIntegral.

  • error , , convert, , .

  • , , , , , . (Convert a b) ? , , .

+4

All Articles