Skip to content

Instantly share code, notes, and snippets.

@sgrif
Last active August 29, 2015 14:00
Show Gist options
  • Save sgrif/b9ec575ead0ca1ce2686 to your computer and use it in GitHub Desktop.
Save sgrif/b9ec575ead0ca1ce2686 to your computer and use it in GitHub Desktop.
class Renderable a where
render :: a -> IO ()
newtype Rectangle = Rectangle { width :: Double, height :: Double }
instance Renderable Rectangle where
render = undefined
newtype Circle = Circle { radius :: Double }
instance Renderable Circle where
render = undefined
renderEverything :: ??? -- Need to render an unknown number of renderables
@pbrisbin
Copy link

pbrisbin commented May 3, 2014

The short answer is this can't be done in Haskell like it can in Scala. The long answer is...

I think it's most common that in a non-contrived system the number of renderables will be known (or at least known within a given domain). This means a type like Game (or multiple situation-dependent types) is both doable and better (because it makes forgetting to render something a type error).

I think it's an unlikely design to have a bunch of primitive shapes at the bottom and a single renderEverything at the top. More likely would be taking the shapes (each of which can be renderable) and grouping them into either lists of the same shape (which can be map . rendered) or structured groupings of different types (which represent some higher level thing in the domain); in these cases the number would be known. This kind of composition would then continue all the way up until you have one big thing that is itself Renderable with many layers between that call to render from main and the shapes of this gist.

type Player = Player
    { playerFace :: Circle
    , playerBody :: Rectangle
    }

instance Renderable Player where

data Weapon = Weapon
    { -- ...
    , -- ...
    }

instance Renderable Weapon where

data Combatant = Combatant Player [Weapon]

instance Renderable Combatant where

data Game = Game [Combatant]

instance Renderable Game where

data Frame = Coroutine Input Game

If you really did want to take this approach you have to use one of the solutions I linked to here. The Existential Types are probably closest to what you want from Scala and was what Rein suggested on Twitter.

I think the simplest solution to the gist as given is an ADT. IMO, hypothetically complicating things to the point where an ADT doesn't work would also get you to a point where a single renderEverything doesn't work either.

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