packages feed

HList-0.4.0.0: examples/prism.hs

{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE QuasiQuotes #-} -- for pun
{-# LANGUAGE TemplateHaskell #-}
module Main where
import Data.HList.CommonMain
import Data.HList.Labelable (hLens')
import Control.Lens

-- generate left = Label :: Label "left"
makeLabels6 (words "left right up down")

--- define the Labelable labels manually
left_ = hLens' left
right_ = hLens' right
up_ = hLens' up
down_ = hLens' down

-- this definition is needed to decide what order
-- to put the fields in, as well as their initial types
r = [pun|right left up|] where
  left = 'a'
  right = 2 :: Int
  up = 2.3 :: Double

v = mkVariant left 'x' r

main = do
    putStrLn "Lookup and set"
    inspectV

    putStrLn "\nrepeat with Labelable"
    inspectV_

    putStrLn "\nSetting the missing tag does nothing:"
    print $ set right_ () v
    Left 'x' <- set _Right () (Left 'x') -- prisms for Either do the same thing
                & return

    putStrLn "\nLenses compose:"
    Nothing  <- v3 ^? up_.up_ & return
    Just 'x' <- v3 ^? left_ & return
    v4 ^? left_.left_ & print

    putStrLn "\nLenses+prisms compose:"
    inspectRV

    putStrLn "\n\"extension\""
    extensionTests

    putStrLn "\nInternal Structure:"
    putStrLn $ indent $ show vs



lazyX = mkVariant (Label :: Label "x") 'a' lazyProto
lazyY = mkVariant (Label :: Label "y") (2.5 :: Double) lazyProto

lazyProto = undefined :: Record
  '[Tagged "x" x, Tagged "y" y]

vs = [pun| v v2 v2' v3 v4 v5 v6 v7 |]

inspectV = do
    v ^? hPrism left & print
    v ^? hPrism right & print
    v ^? hPrism up & print
    v2 ^? hPrism left & print

-- note that we can change the type of the 'x' field
-- from Char to ()
v2 = set (hPrism left) () v

inspectV_ = do
    v ^? left_ & print
    v ^? right_ & print
    v ^? up_ & print
    v2' ^? left_ & print


inspectRV = do
    r2 ^? down_.left_ & print
    r2 ^? down_.right_ & print
    r2 ^? du & print

du = down_.up_

r2 = down_ .==. v .*. r


-- or with the "better" label
v2' = set left_ () v


v3 = v & up_ .~ v & up_.up_ .~ "upup"
v4 = v & left_ .~ v & left_.left_ .~ "leftleft"


extensionTests = do
    Just "hi" <- v5 ^? down_ & return
    Just "hi" <- v6 ^? down_ & return
    Nothing   <- v7 ^? down_ & return
    Just 'x'  <- v7 ^? left_ & return
    return ()


v5 = down .=. Just "hi" .*. v
v6 = down_ .==. Just "hi" .*. v
v7 = down .=. (Nothing :: Maybe String) .*. v

-- start a newline after every } to make the results readable
indent :: String -> String
indent xs = indent' 0 xs

indent' n xs | n < 0 = indent' 0 xs
indent' n ('}' : xs) = "}\n" ++ replicate n ' ' ++ indent' (n-4) xs
indent' n ('{' : xs) = '{' : indent' (n+4) xs
indent' n (x : xs) = x : indent' n xs
indent' _ [] = []