Skip to content

Instantly share code, notes, and snippets.

@kgadek
Last active August 29, 2015 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kgadek/6a919ececea371de5552 to your computer and use it in GitHub Desktop.
Save kgadek/6a919ececea371de5552 to your computer and use it in GitHub Desktop.
Cool polymorphism
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, GADTs, RankNTypes #-}
class HasX a b | a -> b where getX :: a -> b
data Point2 where
Point2 :: Int -> Int -> Point2
data Point3 where
Point3 :: Float -> Float -> Float -> Point3
instance HasX Point2 Int where getX (Point2 x _) = x
instance HasX Point3 Float where getX (Point3 x _ _) = x
--myIf :: (Show a1, Show b1, Show c1,
-- HasX a a1, HasX b b1, HasX c c1
-- ) => Bool -> a -> b -> c1
--myIf bool a b | bool = getX a
-- | otherwise = getX b
--example = show res
-- where
-- res = myIf True (Point2 1 2) (Point3 0.0 0.1 0.2
myIf :: (Show a1, Show b1,
HasX a a1, HasX b b1
) => Bool
-> a
-> b
-> (forall c c1. (HasX c c1, Show c1) => c
-> r)
-> r
myIf True a b k = k a
myIf False a b k = k b
example = myIf False (Point2 1 2) (Point3 0.0 0.1 0.2) (show.getX)
@Saizan
Copy link

Saizan commented Jan 13, 2015

myIf :: (Show a1, Show b1,
HasX a a1, HasX b b1) => Bool -> a -> b -> (forall c1. Show c1 => c1 -> r) -> r
myIf True a b k = k (getX a)
myIf False a b k = k (getX b)

example = myIf True (Point2 1 2) (Point3 0.0 0.1 0.2) show

@kgadek
Copy link
Author

kgadek commented Jan 13, 2015

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, GADTs, RankNTypes #-}

class HasX a b | a -> b where getX :: a -> b

data Point2 where
  Point2 :: Int -> Int -> Point2
data Point3 where
  Point3 :: Float -> Float -> Float -> Point3

instance HasX Point2 Int   where getX (Point2 x _) = x
instance HasX Point3 Float where getX (Point3 x _ _) = x

--myIf :: (Show a1, Show b1, Show c1,
--         HasX a a1, HasX b b1, HasX c c1
--        ) => Bool -> a -> b -> c1
--myIf bool a b | bool      = getX a
--              | otherwise = getX b


--example = show res
--  where
--    res = myIf True (Point2 1 2) (Point3 0.0 0.1 0.2


myIf :: (Show a1, Show b1,
         HasX a a1, HasX b b1
        ) => Bool 
          -> a
          -> b
          -> (forall c. (HasX c c1, Show c1) => c
                                             -> r)
          -> r
myIf True  a b k = k a
myIf False a b k = k b

example = myIf False (Point2 1 2) (Point3 0.0 0.1 0.2) (show.getX)

This results in

GHCi, version 7.8.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[1 of 1] Compiling Main             ( test.hs, interpreted )

test.hs:33:20:
    Could not deduce (HasX a c1) arising from a use of ‘k’
    from the context (Show a1, Show b1, HasX a a1, HasX b b1)
      bound by the type signature for
                 myIf :: (Show a1, Show b1, HasX a a1, HasX b b1) =>
                         Bool -> a -> b -> (forall c. (HasX c c1, Show c1) => c -> r) -> r
      at test.hs:(25,9)-(32,14)
    Possible fix:
      add (HasX a c1) to the context of
        the type signature for
          myIf :: (Show a1, Show b1, HasX a a1, HasX b b1) =>
                  Bool -> a -> b -> (forall c. (HasX c c1, Show c1) => c -> r) -> r
    In the expression: k a
    In an equation for ‘myIf’: myIf True a b k = k a

test.hs:34:20:
    Could not deduce (HasX b c1) arising from a use of ‘k’
    from the context (Show a1, Show b1, HasX a a1, HasX b b1)
      bound by the type signature for
                 myIf :: (Show a1, Show b1, HasX a a1, HasX b b1) =>
                         Bool -> a -> b -> (forall c. (HasX c c1, Show c1) => c -> r) -> r
      at test.hs:(25,9)-(32,14)
    Possible fix:
      add (HasX b c1) to the context of
        the type signature for
          myIf :: (Show a1, Show b1, HasX a a1, HasX b b1) =>
                  Bool -> a -> b -> (forall c. (HasX c c1, Show c1) => c -> r) -> r
    In the expression: k b
    In an equation for ‘myIf’: myIf False a b k = k b
Failed, modules loaded: none.

@kgadek
Copy link
Author

kgadek commented Jan 13, 2015

With help of @Saizan:

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, GADTs, RankNTypes #-}

class HasX a b | a -> b where getX :: a -> b

data Point2 where
  Point2 :: Int -> Int -> Point2
data Point3 where
  Point3 :: Float -> Float -> Float -> Point3

instance HasX Point2 Int   where getX (Point2 x _) = x
instance HasX Point3 Float where getX (Point3 x _ _) = x


myIf :: (Show a1, Show b1,
         HasX a a1, HasX b b1
        ) => Bool 
          -> a
          -> b
          -> (forall c c1. (HasX c c1, Show c1) => c
                                                -> r)
          -> r
myIf True  a b k = k a
myIf False a b k = k b

example = myIf False (Point2 1 2) (Point3 0.0 0.1 0.2) (show.getX)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment