ede-0.2.1: src/Text/EDE/Filters.hs
{-# LANGUAGE ExtendedDefaultRules #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_GHC -fno-warn-type-defaults #-}
-- Module : Text.EDE.Filters
-- Copyright : (c) 2013-2014 Brendan Hay <brendan.g.hay@gmail.com>
-- License : This Source Code Form is subject to the terms of
-- the Mozilla Public License, v. 2.0.
-- A copy of the MPL can be found in the LICENSE file or
-- you can obtain it at http://mozilla.org/MPL/2.0/.
-- Maintainer : Brendan Hay <brendan.g.hay@gmail.com>
-- Stability : experimental
-- Portability : non-portable (GHC extensions)
-- | A default set of prelude-like filters and the means to construct your own.
--
-- Please be aware that some of the 'defaultFilters' are assumed to be present
-- (for example during loop unrolling and assignment of else branches via 'empty').
--
-- It's recommended you supplement the default filters rather than replacing them
-- completely. (But hey, it's your call!)
module Text.EDE.Filters
(
-- * Prelude
defaultFilters
-- ** Boolean
-- $boolean
-- ** Equality
-- $equality
-- ** Relational
-- $relational
-- ** Numeric
-- $numeric
-- ** Fractional
-- $fractional
-- ** Textual
-- $textual
-- ** Collection
-- $collection
-- ** Polymorphic
-- $polymorphic
-- * Constructing filters
, Binding (..)
-- ** Classes
, Quote (..)
, Unquote (..)
-- ** Restricted quoters
, qapply
, qpoly2
, qnum1
, qnum2
, qcol1
-- ** Errors
, unexpected
, typeOf
) where
import Data.Aeson (Value, encode)
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as Map
import Data.Scientific (Scientific)
import Data.Text (Text)
import qualified Data.Text as Text
import qualified Data.Text.Lazy as LText
import qualified Data.Text.Lazy.Encoding as LText
import Data.Text.Manipulate
import qualified Data.Vector as Vector
import Text.EDE.Internal.HOAS
default (Integer)
defaultFilters :: HashMap Text Binding
defaultFilters = Map.unions
[ boolean
, equality
, relational
, numeric
, fractional
, textual
, collection
, polymorphic
]
-- $boolean
--
-- * @!@ @:: Bool -> Bool@ (/See:/ 'not')
--
-- * '&&' @:: Bool -> Bool -> Bool@
--
-- * '||' @:: Bool -> Bool -> Bool@
boolean :: HashMap Text Binding
boolean = Map.fromList
[ "!" @: quote not
, "&&" @: quote (&&)
, "||" @: quote (||)
]
-- $equality
--
-- * '==' @:: a -> a -> Bool@
--
-- * @!=@ @:: a -> a -> Bool@ (/See/: '/=')
equality :: HashMap Text Binding
equality = Map.fromList
[ "==" @: qpoly2 (==)
, "!=" @: qpoly2 (/=)
]
-- $relational
--
-- * '>' @:: a -> a -> Bool@
--
-- * '>=' @:: a -> a -> Bool@
--
-- * '<=' @:: a -> a -> Bool@
--
-- * '<=' @:: a -> a -> Bool@
relational :: HashMap Text Binding
relational = Map.fromList
[ ">" @: qnum2 (>)
, ">=" @: qnum2 (>=)
, "<=" @: qnum2 (<=)
, "<" @: qnum2 (<)
]
-- $numeric
--
-- * '+' @:: Number -> Number -> Number@
--
-- * '-' @:: Number -> Number -> Number@
--
-- * '*' @:: Number -> Number -> Number@
--
-- * 'abs' @:: Number -> Number@
--
-- * 'signum' @:: Number -> Number@
--
-- * 'negate' @:: Number -> Number@
numeric :: HashMap Text Binding
numeric = Map.fromList
[ "+" @: qnum2 (+)
, "-" @: qnum2 (-)
, "*" @: qnum2 (*)
, "abs" @: qnum1 abs
, "signum" @: qnum1 signum
, "negate" @: qnum1 negate
]
-- $fractional
--
-- * 'truncate' @:: Number -> Number@
--
-- * 'round' @:: Number -> Number@
--
-- * 'ceiling' @:: Number -> Number@
--
-- * 'floor' @:: Number -> Number@
fractional :: HashMap Text Binding
fractional = Map.fromList
[ "truncate" @: qnum1 (fromIntegral . truncate)
, "round" @: qnum1 (fromIntegral . round)
, "ceiling" @: qnum1 (fromIntegral . ceiling)
, "floor" @: qnum1 (fromIntegral . floor)
]
-- $textual
--
-- * @takeWord@ @:: Text -> Text@
--
-- * @dropWord@ @:: Text -> Text@
--
-- * @lowerHead@ @:: Text -> Text@
--
-- * @upperHead@ @:: Text -> Text@
--
-- * @toTitle@ @:: Text -> Text@
--
-- * @toCamel@ @:: Text -> Text@
--
-- * @toPascal@ @:: Text -> Text@
--
-- * @toSnake@ @:: Text -> Text@
--
-- * @toSpinal@ @:: Text -> Text@
--
-- * @toTrain@ @:: Text -> Text@
--
-- * @toLower@ @:: Text -> Text@
--
-- * @toUpper@ @:: Text -> Text@
--
-- * @toOrdinal@ @:: Number -> Text@
--
-- /See:/ <http://hackage.haskell.org/package/text-manipulate text-manipulate>
textual :: HashMap Text Binding
textual = Map.fromList
[ "takeWord" @: quote takeWord
, "dropWord" @: quote dropWord
, "lowerHead" @: quote lowerHead
, "upperHead" @: quote upperHead
, "toTitle" @: quote toTitle
, "toCamel" @: quote toCamel
, "toPascal" @: quote toPascal
, "toSnake" @: quote toSnake
, "toSpinal" @: quote toSpinal
, "toTrain" @: quote toTrain
, "toUpper" @: quote Text.toUpper
, "toLower" @: quote Text.toLower
, "toOrdinal" @: (toOrdinal . truncate :: Scientific -> Text)
]
-- $collection
--
-- * @length@ @:: Collection -> Number@ (/See/: 'Data.Text.length', 'Data.Vector.length', 'Data.HashMap.Strict.size')
--
-- * @empty@ @:: Collection -> Bool@ (/See/: 'Data.Text.null', 'Data.Vector.null', 'Data.HashMap.Strict.null')
collection :: HashMap Text Binding
collection = Map.fromList
[ "length" @: qcol1 Text.length Map.size Vector.length
, "empty" @: qcol1 Text.null Map.null Vector.null
-- , ("join", quote
]
-- $polymorphic
--
-- * 'show' @:: a -> Text@
polymorphic :: HashMap Text Binding
polymorphic = Map.fromList
[ "show" @: quote value
]
(@:) :: Quote a => Text -> a -> (Text, Binding)
k @: q = (k, quote q)
value :: Value -> LText.Text
value = LText.decodeUtf8 . encode