Skip to content

Latest commit

 

History

History
60 lines (54 loc) · 1.87 KB

Exercise03.md

File metadata and controls

60 lines (54 loc) · 1.87 KB
module Exercise03 where

import ClassyPrelude
import Data.Aeson (ToJSON, FromJSON, Value (String), parseJSON, toJSON, withText)
import Language.Haskell.TH

import Exercise02

Recall our helper functions trimAndLowerTH, extractConstructors, spliceConstructors, spliceValues. We can combine them to generate instances for FromJSON, ToJSON, and PrettyShow.

Exercises

Derive enum instances for the Pet type

-- |`deriveEnumInstances tyName` takes a type name and derives three instances: `ToJSON`, `FromJSON`, `PrettyShow`. In
-- order to derive those instances we need to extract the constructors and invoke the `spliceConstructors` or
-- `spliceValues` function depending on what type of instance it is (showing or parsing, respectively). For the `Pet`
-- example you would pass in something like:
--
-- @
-- putStrLn $(stringE . pprint =<< deriveEnumInstances ''Pet)
-- @
--
-- and get something like:
--
-- @
-- Instance PrettyShow Pet where
--   prettyShow = \ case
--     PetDog -> "dog"
--     PetCat -> "cat"
--     PetTeddyBear -> "teddyBear"
-- Instance ToJSON Pet where
--   toJSON = \ case
--     PetDog -> String "dog"
--     PetCat -> String "cat"
--     PetTeddyBear -> String "teddyBear"
-- Instance FromJSON Pet where
--   parseJSON = withText "Pet" $ \ case
--     "dog" -> pure PetDog
--     "cat" -> pure PetCat
--     "teddyBear" -> pure PetTeddyBear
--     other -> fail $ "I don't know about " <> other
-- @
--
-- Fill in the body given the function arguments.
deriveEnumInstances :: Name -> Q [Dec]
deriveEnumInstances tyName = do
  conNames <- fail "TODO fill me in"
  [d| instance PrettyShow $(conT tyName) where
        prettyShow = error "TODO fill me in"
      instance ToJSON $(conT tyName) where
        toJSON = error "TODO fill me in"
      instance FromJSON $(conT tyName) where
        parseJSON = error "TODO fill me in"
    |]