Skip to content

Instantly share code, notes, and snippets.

@guibou
Last active March 22, 2021 19:51
Show Gist options
  • Select an option

  • Save guibou/0e2d5597500a12c3579365e594a4079b to your computer and use it in GitHub Desktop.

Select an option

Save guibou/0e2d5597500a12c3579365e594a4079b to your computer and use it in GitHub Desktop.
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FlexibleInstances #-}
import GHC.Float
class RealToFrac a where
convert :: a -> Double
instance {-# OVERLAPPABLE #-} Real t => RealToFrac t where convert = realToFrac
instance RealToFrac Double where convert = id
instance RealToFrac Float where convert = float2Double
-- Version without the fundep
class RealToFrac' a b where
convert' :: a -> b
instance {-# OVERLAPPABLE #-} Real t => RealToFrac' t Double where convert' = realToFrac
instance RealToFrac' Double Double where convert' = id
instance RealToFrac' Float Float where convert' = id
-- Here GHC is not able to deduce b
-- chien :: (Show b, RealToFrac' a b) => a -> String
-- chien = show . convert'
-- That's why I want a fundep
class RealToFrac'' a b | a -> b where
convert'' :: a -> b
-- this instance is impossible because it conflicts with fundeps
-- instance {-# OVERLAPPABLE #-} Real t => RealToFrac'' t Double where convert'' = realToFrac
instance RealToFrac'' Double Double where convert'' = id
instance RealToFrac'' Float Float where convert'' = id
-- Here GHC is able to deduce b
chien' :: (Show b, RealToFrac'' a b) => a -> String
chien' = show . convert''
-- Solution with closed type family
type family ToRealFracT t where
ToRealFracT Double = Double
ToRealFracT Float = Float
ToRealFracT t = Double
--
--
class RealToFrac''' a where
convert''' :: a -> ToRealFracT a
instance {-# OVERLAPPABLE #-} (ToRealFracT t ~ Double, Real t) => RealToFrac''' t where convert''' = realToFrac
instance RealToFrac''' Double where convert''' = id
instance RealToFrac''' Float where convert''' = id
-- Here GHC is able to deduce b
chien'' :: (Show (ToRealFracT a), RealToFrac''' a) => a -> String
chien'' = show . convert'''
-- Solution with open type family
type family ToRealFracTOpen t
type instance ToRealFracTOpen Double = Double
type instance ToRealFracTOpen Float = Float
-- This one is not possible
-- type instance ToRealFracTOpen t = Double
--
--
class RealToFrac'''' a where
convert'''' :: a -> ToRealFracTOpen a
-- this instance is impossible because it conflicts with fundeps
instance {-# OVERLAPPABLE #-} (ToRealFracTOpen t ~ Double, Real t) => RealToFrac'''' t where convert'''' = realToFrac
instance RealToFrac'''' Double where convert'''' = id
instance RealToFrac'''' Float where convert'''' = id
-- Here GHC is able to deduce b
chien''' :: (Show (ToRealFracTOpen a), RealToFrac'''' a) => a -> String
chien''' = show . convert''''
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment