packages feed

serpentine-0.2: example/main.hs

{-# LANGUAGE GADTs, TypeFamilies,DataKinds,PolyKinds,KindSignatures #-}
{-# LANGUAGE RankNTypes,TypeOperators,OverloadedStrings #-}
{-# LANGUAGE UndecidableInstances, TemplateHaskell, ScopedTypeVariables #-}
{-# LANGUAGE InstanceSigs, FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# OPTIONS_GHC -Wall #-}
{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}

module Main where

import Prelude
import Data.Text (Text)
import Data.Typeable 
import Data.Singletons.TH
import Data.Singletons.Prelude
import Serpentine
import Serpentine.Crud
import Serpentine.PathPiece
import qualified Data.Text as Text
import qualified Data.Text.IO as Text

data Foo   = Bar | Baz
data Thing = This | That Foo
data Color = Red | Green | Blue Thing

$(singletons [d|
  data MyRoute = UsersR 
               | ProfileR 
               | DogR CrudRoute 
               | HouseR CrudRoute 
               | RenameR
    deriving (Eq,Ord,Show)
  instance Enum MyRoute where
    toEnum i
      | i == 0            = UsersR
      | i == 1            = ProfileR
      | i >= 2 && i <= 5  = DogR (toEnum (i - 2))
      | i >= 6 && i <= 9  = HouseR (toEnum (i - 6))
      | i == 10           = RenameR
    fromEnum a = go a
      where
      go UsersR = 0
      go ProfileR = 1
      go RenameR = 10
      go (DogR c) = 2 + fromEnum c
      go (HouseR c) = 6 + fromEnum c
  instance Bounded MyRoute where
    minBound = UsersR
    maxBound = RenameR
  |])

-- myChar :: Char
-- myChar = 'T'
-- 
-- colorToChar :: Color -> Char
-- colorToChar c = $(constConstructors 'c ''Color 'myChar)

newtype DogId = DogId { getDogId :: Int }
  deriving (Eq,Ord,Typeable,PathPiece)

type family PlanMyRoute (k :: MyRoute) :: [Piece *] where
  PlanMyRoute 'UsersR        = '[ 'Static "user", 'Static "index"]
  PlanMyRoute 'ProfileR      = '[ 'Static "user", 'Static "profile", 'Capture Int]
  PlanMyRoute 'RenameR       = '[ 'Static "user", 'Static "edit", 'Capture Int, 'Capture Text]
  PlanMyRoute ('DogR crud)   = 'Static "dog"   ': PlanCrudRoute DogId crud
  PlanMyRoute ('HouseR crud) = 'Static "house" ': PlanCrudRoute Int crud
genDefunSymbols [''PlanMyRoute]

-- sPlanMyRoute :: SMyRoute route -> SList (PlanMyRoute route)
-- sPlanMyRoute r = case r of
--   SUsersR   -> defPieces
--   SProfileR -> defPieces
--   SRenameR  -> defPieces
--   SDogR c   -> SCons (SStatic :: SPiece ('Static "dog")) (sPlanCrudRoute (Proxy :: Proxy DogId) c)
--   SHouseR c -> SCons (SStatic :: SPiece ('Static "house")) (sPlanCrudRoute (Proxy :: Proxy Int) c)

sPlanMyRoute :: SMyRoute route -> SList (PlanMyRoute route)
sPlanMyRoute r = $(constConstructors 'r ''MyRoute 'defPieces)

parseMyRoute :: [Text] -> Maybe (SomeRoutePieces PlanMyRouteSym0)
parseMyRoute = parseAllRoutes (Proxy :: Proxy PlanMyRouteSym0) sPlanMyRoute

renderMyRoute :: Sing route 
              -> IRec (PiecesNestedTuple (PlanMyRoute route))
              -> [Text] 
renderMyRoute = render (Proxy :: Proxy PlanMyRouteSym0) sPlanMyRoute

main :: IO ()
main = do
  r SProfileR     (44 :& IRNil)
  r SRenameR      (33 :& "Bob" :& IRNil)
  r (SDogR SAddR) (IRNil)
  print (p "/bad/path")
  print (p "/user/edit/12/Jonathon")
  print (p "/house/edit/66")
  print (p "/dog/add")
  where 
  r a = Text.putStrLn 
      . Text.cons '/'
      . Text.intercalate "/"
      . renderMyRoute a
  p   = parseMyRoute
      . filter (not . Text.null) 
      . Text.splitOn "/"