Skip to content

Instantly share code, notes, and snippets.

@Decoherence
Last active August 29, 2015 14:11
Show Gist options
  • Save Decoherence/24f47499082c642b300e to your computer and use it in GitHub Desktop.
Save Decoherence/24f47499082c642b300e to your computer and use it in GitHub Desktop.
Haskell: Using existential quantification to calculate the area of a heterogeneous list of shapes.
{-# LANGUAGE ExistentialQuantification #-}
data Circle = Circle Double deriving (Show)
data Square = Square Double deriving (Show)
data Rectangle = Rectangle Double Double deriving (Show)
--------------------------------------------------------------------------------
-- Each shape implements an area function
--------------------------------------------------------------------------------
class Shape s where
area :: s -> Double
instance Shape Circle where
area (Circle r) = pi * r*r
instance Shape Square where
area (Square x) = x * x
instance Shape Rectangle where
area (Rectangle l w) = l * w
--------------------------------------------------------------------------------
-- Our Shapes
--------------------------------------------------------------------------------
rect :: Rectangle
rect = Rectangle 2 4
cir :: Circle
cir = Circle 1
sq :: Square
sq = Square 2
{-
Our area function can be used with:
1. an individual shape
2. a list of the same shape (e.g. a list of Circles)
But what about a list of various shapes?
-}
--------------------------------------------------------------------------------
-- A generic container to hold shapes (using ExistentialQuantification)
--------------------------------------------------------------------------------
data ShapeBox = forall s. (Show s, Shape s) => SB s
-- We can print each Shape in our ShapeBox
instance Show ShapeBox where
show (SB s) = show s
-- We can find the area of each Shape in our ShapeBox
instance Shape ShapeBox where
area (SB s) = area s
shapeList :: [ShapeBox]
shapeList = [SB rect, SB cir, SB sq]
main :: IO ()
main = do
putStrLn "We have three shapes:\n"
sequence_ [print rect, print cir, print sq]
putStrLn "\nOur list of shapes, each wrapped in a ShapeBox:\n"
print shapeList
putStrLn "\nLet's print each one:\n"
mapM_ print shapeList
putStrLn "\nNow let's map the area function to each shape:\n"
mapM_ (print . area) shapeList
{-
OUTPUT:
> main
We have three shapes:
Rectangle 2.0 4.0
Circle 1.0
Square 2.0
Our list of shapes, each wrapped in a ShapeBox:
[Rectangle 2.0 4.0,Circle 1.0,Square 2.0]
Let's print each one:
Rectangle 2.0 4.0
Circle 1.0
Square 2.0
Now let's map the area function to each shape:
8.0
3.141592653589793
4.0
-}
{-# LANGUAGE DataKinds #-}
data Shapes = Circle Double | Square Double | Rectangle Double Double
deriving (Show)
class Shape s where
area :: s -> Double
instance Shape Shapes where
area (Circle r) = pi * r * r
area (Square l) = l * l
area (Rectangle l w) = l * w
shapeList :: [Shapes]
shapeList = [Square 2, Circle 1, Rectangle 2 3]
main :: IO ()
main = do
print $ area (Circle 1)
print $ area (Square 2)
print shapeList
print $ map area shapeList
{-
OUTPUT:
> main
3.141592653589793
4.0
[Square 2.0,Circle 1.0,Rectangle 2.0 3.0]
[4.0,3.141592653589793,6.0]
-}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment