Created
June 12, 2018 10:36
-
-
Save rupertlssmith/fe24d4f740fa9b622a3c329fc2330772 to your computer and use it in GitHub Desktop.
Traits in Elm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Traits exposing (..) | |
type GameState | |
= State | |
{-| FireTrait defines how the game state is updated for any kind of shooting | |
event. | |
's' is the state implementation parameter, | |
'a' makes the trait extensible so that traits can be combined. | |
-} | |
type alias FireTrait s a = | |
{ a | |
| fire : s -> GameState -> GameState | |
} | |
type alias Gun a = | |
{ a | |
| power : Float | |
, turretSize : Int | |
} | |
{-| A castle has a gun and a shield. | |
-} | |
type alias Castle = | |
Gun { shield : Float } | |
{-| A zap monster has a gun and health and a special zapping power. | |
-} | |
type alias ZapMonster = | |
Gun | |
{ health : Float | |
, zapPower : Float | |
} | |
type alias CastleTraits = | |
FireTrait Castle {} | |
type alias ZapMonsterTraits = | |
FireTrait ZapMonster {} | |
{-| How to update the game state when a gun is fired - only needs to be written once. | |
-} | |
fireGun : Gun a -> GameState -> GameState | |
fireGun _ state = | |
state | |
{-| How to update the game state for any firing trait - only needs to be written once. | |
-} | |
updateForFiring : FireTrait s a -> s -> GameState -> GameState | |
updateForFiring fireTrait gameObject state = | |
fireTrait.fire gameObject state | |
-- Example with castles and zap monsters both with normal guns. | |
castleTraits : CastleTraits | |
castleTraits = | |
{ fire = fireGun } | |
zapMonsterTraits : ZapMonsterTraits | |
zapMonsterTraits = | |
{ fire = fireGun } | |
castle : Castle | |
castle = | |
{ power = 100, turretSize = 5, shield = 100 } | |
zapMonster : ZapMonster | |
zapMonster = | |
{ power = 60, turretSize = 2, health = 100, zapPower = 20 } | |
gameState1 = | |
updateForFiring castleTraits castle State | |
gameState2 = | |
updateForFiring zapMonsterTraits zapMonster gameState1 | |
-- Example with a zap monster upgraded to use its special zap ability. | |
-- A new fire implementation is written, but the existing update logic is | |
-- re-used as it was coded for the general trait. | |
fireZap : ZapMonster -> GameState -> GameState | |
fireZap _ state = | |
state | |
zapMonsterTraits2 : ZapMonsterTraits | |
zapMonsterTraits2 = | |
{ fire = fireZap } | |
gameState3 = | |
updateForFiring zapMonsterTraits2 zapMonster gameState2 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment