packages feed

caseof 0.0.0 → 0.0.1

raw patch · 3 files changed

+50/−23 lines, 3 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- CaseOf: nameAsValue :: Name -> Q Name
+ CaseOf: mapCaseOf :: Name -> Q Exp

Files

README.md view
@@ -3,6 +3,9 @@ A simple way to query constructors, like cases but slightly more concise. +Prisms from the lens package can also manage this, but this is a bit+simpler.+ Aimed at sum types with many constructors:  ``` haskell@@ -23,6 +26,13 @@ Just (1,'a') ``` +There is a "map" over a constructor:++``` haskell+> $(mapCaseOf 'Left) succ (Left 3)+Left 4+```+ There is a combinator which calls your function with n arguments, or passes the whole value to an "else" clause. @@ -30,27 +40,6 @@ > $(caseOf 'Woo) (\x y -> show x ++ show y) (const "") (Wibble 5) "" ```--This allows them to be nested:--```haskell-> $(caseOf 'Woo) (\x y -> show x ++ show y) (const "") (Woo 5 'a')-"5'a'"-> $(caseOf 'Woo) (\x y -> show x ++ show y) ($(caseOf 'Wibble) show (const "")) (Woo 5 'a')-"5'a'"-```--What's the point of `caseOf`? To more easily dispatch on functions:--```haskell-handleHuman name age = ...-handleMachine id = ..-handleWithDefault def =-   $(caseOf 'Human) handleHuman .-   $(caseOf 'Machine) handleMachine def-```--This applies to any kind of "case" that you'd like to refactor into a function.  ## Use in your project 
caseof.cabal view
@@ -1,5 +1,5 @@ name:                caseof-version:             0.0.0+version:             0.0.1 synopsis:            Combinators for casing on constructors description:         Template-Haskell-based combinators that let you select on constructors. homepage:            https://github.com/chrisdone/caseof#readme
src/CaseOf.hs view
@@ -2,8 +2,15 @@ {-# LANGUAGE LambdaCase #-} {-# LANGUAGE TemplateHaskell #-} -module CaseOf where+-- | Template-Haskell-based combinators that let you select on constructors. +module CaseOf+  (isCaseOf+  ,maybeCaseOf+  ,mapCaseOf+  ,caseOf)+  where+ import Language.Haskell.TH import Language.Haskell.TH.Syntax @@ -34,6 +41,37 @@            ])     _ -> fail ("Invalid data constructor " ++ pprint input)   where+    varI i = VarE (mkName ("v" ++ show i))+    patI i = VarP (mkName ("v" ++ show i))+    arity (ForallT _ _ t) = arity t+    arity (AppT (AppT ArrowT _) y) = 1 + arity y+    arity _ = 0++-- | Apply a function to the slots of a constructor, if it matches,+-- otherwise identity.+mapCaseOf :: Name -> Q Exp+mapCaseOf input = do+  name <- nameAsValue input+  info <- reify name+  case info of+    DataConI _ ty _ ->+      pure+        (LamE+           [VarP f]+           (LamCaseE+              [ Match+                  (ConP name (map patI [1 .. arity ty]))+                  (NormalB+                     (AppE+                        (ConE name)+                        (foldl AppE (VarE f) (map varI [1 .. arity ty]))))+                  []+              , Match (VarP this) (NormalB (VarE this)) []+              ]))+    _ -> fail ("Invalid data constructor " ++ pprint input)+  where+    f = mkName "f"+    this = mkName "this"     varI i = VarE (mkName ("v" ++ show i))     patI i = VarP (mkName ("v" ++ show i))     arity (ForallT _ _ t) = arity t