-- Copyright (c) Microsoft. All rights reserved. -- Licensed under the MIT license. See LICENSE file in the project root for full license information. {-# LANGUAGE OverloadedStrings #-} {-| Copyright : (c) Microsoft License : MIT Maintainer : adamsap@microsoft.com Stability : provisional Portability : portable Helper functions for combining elements into common constructs. These functions can be used in code generation to lazily combine 'Text' elements but they are more generic and work for any 'Monoid'. -} module Language.Bond.Util ( sepBy , sepEndBy , sepBeginBy , optional , angles , brackets , braces , parens , between ) where import Data.Monoid import Data.String (IsString) import Prelude sepEndBy, sepBeginBy, sepBy :: (Monoid a, Eq a) => a -> (b -> a) -> [b] -> a -- | Maps elements of a list and combines them with 'mappend' using given -- separator, ending with a separator. sepEndBy _ _ [] = mempty sepEndBy s f (x:xs) | next == mempty = rest | otherwise = next <> s <> rest where next = f x rest = sepEndBy s f xs -- | Maps elements of a list and combines them with 'mappend' using given -- separator, starting with a separator. sepBeginBy _ _ [] = mempty sepBeginBy s f (x:xs) | next == mempty = rest | otherwise = s <> next <> rest where next = f x rest = sepBeginBy s f xs -- | Maps elements of a list and combines them with 'mappend' using given -- separator. sepBy _ _ [] = mempty sepBy s f (x:xs) | null xs = next | next == mempty = rest | otherwise = next <> sepBeginBy s f xs where next = f x rest = sepBy s f xs -- | The function takes a function and a Maybe value. If the Maybe value is -- Nothing, the function returns 'mempty', otherwise, it applies the function -- to the value inside 'Just' and returns the result. optional :: (Monoid m) => (a -> m) -> Maybe a -> m optional = maybe mempty -- | If the 3rd argument is not 'mempty' the function wraps it between the -- first and second argument using 'mappend', otherwise it return 'mempty'. between :: (Monoid a, Eq a) => a -> a -> a -> a between l r m | m == mempty = mempty | otherwise = l <> m <> r angles, brackets, braces, parens :: (Monoid a, IsString a, Eq a) => a -> a -- | Wraps the string argument between @<@ and @>@, unless the argument is -- 'mempty' in which case the function returns 'mempty'. angles m = between "<" ">" m -- | Wraps the string argument between @[@ and @]@, unless the argument is -- 'mempty' in which case the function returns 'mempty'. brackets m = between "[" "]" m -- | Wraps the string argument between @{@ and @}@, unless the argument is -- 'mempty' in which case the function returns 'mempty'. braces m = between "{" "}" m -- | Wraps the string argument between @(@ and @)@, unless the argument is -- 'mempty' in which case the function returns 'mempty'. parens m = between "(" ")" m