Is there a way to define a function like so:
f :: (C a, C b) => a -> Maybe b
Such that:
f = Just
when type a
= b
, and
f _ = Nothing
when type a
/= b
?
Note that:
C
, but I'm pretty sure it's necessary (particularly if I want to avoid overlapping instances).Equal a b
makes this problem trivial but it then requires n^2
instances which I want to avoid.http://hackage.haskell.org/package/base-4.9.1.0/docs/Data-Typeable.html#v:cast
cast :: (Typeable a, Typeable b) => a -> Maybe b
Function cast can be a part of "type casting system like object-oriented languages". Bacteria and Fungus are Life. They can be upcasted to Life. And Life may be able to downcast to Bacteria or Fungus.
{-# LANGUAGE ExistentialQuantification, DeriveDataTypeable #-}
import Data.Typeable
import Data.Maybe
data SomeLife = forall l . Life l => SomeLife l
deriving Typeable
instance Show SomeLife where
show (SomeLife l) = "SomeLife " ++ show l
class (Typeable l, Show l) => Life l where
toLife :: l -> SomeLife
fromLife :: SomeLife -> Maybe l
toLife = SomeLife
fromLife (SomeLife l) = cast l
instance Life SomeLife where
toLife = id
fromLife = Just
data Bacteria = Bacteria deriving (Typeable, Show)
instance Life Bacteria
data Fungus = Fungus deriving (Typeable, Show)
instance Life Fungus
castLife :: (Life l1, Life l2) => l1 -> Maybe l2
castLife = fromLife . toLife
filterLife :: (Life l1, Life l2) => [l1] -> [l2]
filterLife = catMaybes . map castLife
withLifeIO :: (Life l1, Life l2) => l1 -> (l2 -> IO ()) -> IO ()
withLifeIO l f = maybe (return ()) f $ castLife l
withYourFavoriteLife :: Life l => (l -> IO ()) -> IO ()
withYourFavoriteLife act = do
withLifeIO Bacteria act
withLifeIO Fungus act
main :: IO ()
main = do
let sls :: Life l => [l]
sls = filterLife [
SomeLife Bacteria,
SomeLife Fungus,
SomeLife Fungus ]
print (sls :: [SomeLife])
print (sls :: [Bacteria])
print (sls :: [Fungus])
withYourFavoriteLife (print :: SomeLife -> IO ())
withYourFavoriteLife (print :: Bacteria -> IO ())
withYourFavoriteLife (print :: Fungus -> IO ())
This technic extend to type hierarchy system. Whole Life module is here. https://github.com/YoshikuniJujo/test_haskell/blob/master/features/existential_quantifications/type_hierarchy/Life.hs
Exception system use this technic. https://hackage.haskell.org/package/base-4.9.1.0/docs/Control-Exception.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With