packages feed

vinyl-0.14.3: tests/XRecSpec.hs

{-# LANGUAGE DataKinds, FlexibleContexts, OverloadedLabels,
             TypeApplications, TypeOperators, ViewPatterns #-}
module XRecSpec (spec) where
import Data.Vinyl
import Data.Vinyl.FromTuple (namedArgs, ruple, xrec, fieldRec, withDefaults)
import Data.Vinyl.Functor ((:.))
import Data.Vinyl.XRec (rgetX)
import Test.Hspec (SpecWith, describe, it, shouldBe)

-- | A function that takes named parameters.
foo :: FieldRec '["name" ::: String, "age" ::: Int] -> Int
foo (ruple -> (name, age)) = length name + age

-- | Like 'foo', but has default values for each parameter.
foo' :: (RMap ss, ss ⊆ '["name" ::: String, "age" ::: Int])
     => Rec ElField ss -> Int
foo' = foo . withDefaults defs
  where defs = fieldRec (#name =: "roberta", #age =: (48 :: Int))

spec :: SpecWith ()
spec = do
  describe "Named Arguments" $ do
    it "Can re-order arguments" $
      foo (namedArgs (#age =: (23 :: Int), #name =: "Joe")) `shouldBe` 26
    it "Can pass too many arguments" $
      foo (namedArgs ( #age =: (23 :: Int)
                     , #isAwesome =: True
                     , #name =: "Cheryl"))
      `shouldBe` 29

  describe "Default arguments" $ do
    it "Can take zero arguments" $
      foo' (fieldRec ()) `shouldBe` 55
    it "Can take a subset of named arguments (1)" $
      foo' (#age =:= (39::Int)) `shouldBe` 46
    it "Can take a subset of named arguments (2)" $
      foo' (#name =:= "Jerome") `shouldBe` 54
    it "Can take all arguments" $
      foo' (fieldRec (#age =: (36::Int), #name =: "Jerome")) `shouldBe` 42

  describe "Can get fields through HKD" $ do
    let myRec :: Rec (Maybe :. ElField) ["name" ::: String, "age" ::: Int]
        myRec = xrec (Just "joe", Just 23)
    it "Can eliminate Compose newtype wrappers" $ do
      rgetX @("age" ::: Int) myRec `shouldBe` Just 23