Skip to content

Instantly share code, notes, and snippets.

@TheSeamau5
Created March 12, 2015 18:51
Show Gist options
  • Save TheSeamau5/6076083ed613a34b58ed to your computer and use it in GitHub Desktop.
Save TheSeamau5/6076083ed613a34b58ed to your computer and use it in GitHub Desktop.

Record Example

The following is an example of how to:

  • create a nested record type
  • encode this as JSON
  • decode a JSON string to an entity
  • create a random Entity generator
  • test the JSON parsing of the Entity

We create the types we need

type alias Vector = 
  { x : Float
  , y : Float
  , z : Float
  }

type alias Transform = 
  { position : Vector
  , rotation : Vector
  , scale : Vector 
  }

type alias ID = Int

type alias Entity = 
  { name : String
  , id : ID
  , transform : Transform
  , 
  }

This is how we do encoding

-- Encoding (Using Encode namespace)
entity : Entity -> String
entity ent = object
  [ "name" := string ent.name
  , "id" := id ent.id
  , "transform" : transform ent.transform 
  ]
    
    
transform : Transform -> String
transform {position, rotation, scale} = object
  [ "position" := vector position
  , "rotation" := vector rotation
  , "scale" := vector scale
  ]
  
vector : Vector -> String
vector {x, y, z} = object
  [ "x" := float x
  , "y" := float y
  , "z" := float z
  ]
  
id : ID -> String
id = int

This is how we do decoding

-- Decoding (Using Decoder namespace)
entity : Decoder Entity
entity = Entity
  `map` "name" := string
  `andMap` "id" := id
  `andMap` "transform" := transform
  
transform : Decoder Transform
transform = Transform 
  `map` "position" := vector
  `andMap` "rotation" := vector
  `andMap` "scale" := scale
  
vector : Decoder Vector
vector = Vector
  `map` "x" := float
  `andMap` "y" := float
  `andMap` "z" := float
  
  
id : Decoder ID
id = int 

This is how we generate a random entity

-- Random Generator (Under Random namespace)
entity : Generator Entity 
entity = Entity 
  `map` rangeLengthString 1 20 unicode
  `andMap` anyInt
  `andMap` transform


transform : Generator Transform
transform = Transform
  `map` vector
  `andMap` vector
  `andMap` vector
  
vector : Generator Vector
vector = Vector
  `map` anyFloat
  `andMap` anyFloat
  `andMap` anyFloat

This is how we test that our JSON encoding and decoding works

--- Property Test 
test_encodeDecode : Entity -> Bool
test_encodeDecode entity = 
  let
      encoded = Encode.entity entity      
      decoded = decodeString Decode.entity entity  
  in case decoded of 
    Err _ -> False
    Ok value -> entity == value
      
  
prop_encodingAndDecodingAreInverses : Property
prop_encodingAndDecodingAreInverses = property 
  "Encoding an Entity and then decoding that encode should return the original Entity"
  test_encodeDecode Random.entity
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment