Skip to content

Instantly share code, notes, and snippets.

@ongyiren1994
Last active April 20, 2021 09:14
Show Gist options
  • Save ongyiren1994/30d406f5b3ec936b2f8ff4b765620a15 to your computer and use it in GitHub Desktop.
Save ongyiren1994/30d406f5b3ec936b2f8ff4b765620a15 to your computer and use it in GitHub Desktop.
A Random Tour of Typeclass in Haskell
-- code examples from https://fpbyintuition.medium.com/
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE NoStarIsType #-}
{-# LANGUAGE KindSignatures #-}
import GHC.Exts (Constraint)
import GHC.Types
import Prelude hiding (Monad, return, (>>=))
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
return :: a -> m a
instance Monad Maybe where
Nothing >>= f = Nothing
(Just x) >>= f = f x
return = Just
instance Monad (Either e) where
return = Right
Left l >>= _ = Left l
Right r >>= k = k r
f :: (Monad m) => String -> m [Char]
f x = return x
g :: a -> Maybe a
g x = Just x >>= return
g' :: (Monad m, m ~ Maybe) => a -> m a
g' x = Just x >>= return
-- > :t return
-- return :: Monad m => a -> m a
--
-- > :t return @Maybe
-- return @Maybe :: a -> Maybe a
--
-- > :t return @Maybe "hello"
-- return @Maybe "hello" :: Maybe [Char]
--
-- > return @Maybe "hello"
-- Just "hello"
class Id m where
identity :: m -> m
instance Id m where
identity m = m
h :: a -> a
h x = identity x
-- instance Id Bool where
-- identity m = not m
--
-- instance {-# OVERLAPPING #-} Id Bool where
-- identity a = not a
-- class Transform a b where
-- transform :: a -> b
-- instance Transform String (Maybe Bool) where
-- transform "True" = Just True
-- transform "False" = Just False
-- transform _ = Nothing
-- instance Transform String (Maybe Int) where
-- transform "zero" = Just 0
-- transform _ = Nothing
-- > transform "1" :: Maybe Bool
-- Nothing
-- > transform @String @(Maybe Bool) "1"
-- Nothing
class Transform a b | a -> b where
transform :: a -> b
instance Transform String (Maybe Bool) where
transform "True" = Just True
transform "False" = Just False
transform _ = Nothing
instance Transform Bool String where
transform True = "True"
transform False = "False"
--
class Transform' a where
type F a
transform' :: a -> F a
instance Transform' String where
type F String = Maybe Bool
-- transform' :: String -> Maybe Bool
-- we substitute (F String) with (Maybe Bool)
transform' "True" = Just True
transform' "False" = Just False
transform' _ = Nothing
instance Transform' Bool where
type F Bool = String
-- transform' :: Bool -> String
-- we substitute (F Bool) with (String)
transform' True = "True"
transform' False = "False"
class Memo a where
data Table a :: Type -> Type
toTable :: (a -> w) -> Table a w
fromTable :: Table a w -> (a -> w)
instance Memo Bool where
data Table Bool w = TBool w w
toTable f = TBool (f True) (f False)
fromTable (TBool x y) b = if b then x else y
-- > :t TBool
-- w -> w -> Table Bool w
class Graph g where
type Vertex g
data Edge g
src, tgt :: Edge g -> Vertex g
outEdges :: g -> Vertex g -> [Edge g]
class Trivial a -- No further definition
instance Trivial a -- No futher implementation
-- > :k Trivial (Either) -- the kind of Trivial is (Type -> Type -> Type) -> Constraint
-- Constraint
-- > :k Trivial (Either Int) -- the kind of Trivial is (Type -> Type) -> Constraint
-- Constraint
-- > :k Trivial (Either Int Int) -- the kind of Trivial is (Type -> Constraint
-- Constraint
data Dict (p :: Constraint) where
Dict :: p => Dict p
-- > :t Dict @(Show Int)
-- Dict (Show Int)
-- > :t Dict @(Eq Int)
-- Dict (Eq Int)
-- > :t Dict @(Trivial Int) -- Let's not forget our trivial typeclass
-- Dict (Trivial Int)
type Cons a = (Eq a, Ord a)
-- > :k Cons Int
-- Constraint
data Direction = North | West | South | East
deriving (Ord, Eq)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment