packages feed

category-printf (empty) → 0.1.0.0

raw patch · 9 files changed

+339/−0 lines, 9 filesdep +basedep +bytestringdep +comonadsetup-changed

Dependencies added: base, bytestring, comonad, text

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2016, Cale Gibbard++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Cale Gibbard nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ category-printf.cabal view
@@ -0,0 +1,34 @@+name:                category-printf+version:             0.1.0.0+synopsis:            Highbrow approach to type-safe printf format specifications.+description:         We use the co-Kleisli category for the comonad of+                     functions out of a fixed monoid to implement a generic+                     combinator library for type-safe format specifications.+                     Works with pretty much anything that's a monoid, with+                     specific support for String, Text (strict/lazy), and+                     ByteString (strict/lazy). Credit to Daniel Patterson+                     for introducing me to something that looked just enough+                     like it ought to be the composition for a category, and+                     Ryan Trinkle for the IsString instance. :)+license:             BSD3+license-file:        LICENSE+author:              Cale Gibbard+maintainer:          cgibbard@gmail.com+category:            Text+build-type:          Simple++-- Constraint on the version of Cabal needed to build this package.+cabal-version:       >=1.10++library+  exposed-modules:     Control.Category.Printf,+                       Control.Category.Printf.String,+                       Control.Category.Printf.Text.Strict,+                       Control.Category.Printf.Text.Lazy,+                       Control.Category.Printf.ByteString.Strict,+                       Control.Category.Printf.ByteString.Lazy+  +  other-extensions:    OverloadedStrings, FlexibleInstances, TypeFamilies+  build-depends:       base >=4.7 && <4.8, comonad >=5 && <5.1, text >=1.1 && <1.2, bytestring >=0.10 && <0.11+  hs-source-dirs:      src+  default-language:    Haskell2010
+ src/Control/Category/Printf.hs view
@@ -0,0 +1,142 @@+{-# LANGUAGE OverloadedStrings, FlexibleInstances, TypeFamilies #-}++module Control.Category.Printf +       ( module Control.Category+       , Format+       , printfWith+       , sprintf+       , c+       , i+       , spliceWith+       , s+       , generalizeString+       , intAtBase+       , hex+       , oct+       , eFloat+       , fFloat+       , gFloat+       , push+       , dup+       , swap+       , skip+       , apply+       , apply2+       ) where++import Prelude hiding (id, (.))+import Control.Arrow+import Control.Category+import Data.Monoid+import Control.Comonad+import Numeric++import Data.String++-- | Handy type synonym for the things we're working with.+type Format m = Cokleisli ((->) m)++-- | You should regard a value of type @Format m a b@ as something which explains how to write+-- some element of the monoid @m@ (a "string" for our purposes), and which will change the type+-- of printf from @a@ to @b@. For instance, something which adds a responsibility to provide an+-- additional argument of type @t@ might have type @Format m a (t -> a)@, while a formatter which+-- somehow absolves you of that responsibility would have type @Format m (t -> a) a@.++-- | We can apply this to something like putStrLn to get a function for formatted printing.+-- Typically you'll have @r = IO ()@, but that needn't be the case.+printfWith :: (m -> r) -> Format m r b -> b+printfWith printer f = runCokleisli f printer++-- | If you just want to build a string / element of your monoid, we have @sprintf = printfWith id@+sprintf :: Format m m b -> b+sprintf = printfWith id++instance (a ~ b, IsString s, Monoid s) => IsString (Cokleisli ((->) s) a b) where+  fromString = c . fromString++-- | Formatter for a constant string.+c :: (Monoid m) => m -> Format m a a+c x = Cokleisli (\k -> k x)++-- | Inclusion of a string directly.+i :: Format m a (m -> a)+i = Cokleisli id++-- | Given a way to turn a value of type t into a string, this builds a+-- formatter which demands an additional argument of type t and splices it in.+spliceWith :: (Monoid m) => (t -> m) -> Format m a (t -> a)+spliceWith f = Cokleisli (\k n -> k (f n))++-- | Splice in anything showable.+s :: (Monoid s, IsString s, Show t) => Format s a (t -> a)+s = spliceWith (fromString . show)++-- | Generalizes the string type that a formatter uses by applying fromString internally.+generalizeString :: (IsString s, Monoid s) => Format String a b -> Format s a b+generalizeString f = Cokleisli (\k -> runCokleisli f (k . fromString))++-- | Show an integral value using the given base, and using the provided function to determine how+-- to display individual digits.+intAtBase :: (Real t, Integral t, Show t, Monoid s, IsString s)+          => t -> (Int -> Char) -> Format s a (t -> a)+intAtBase b showDigit = generalizeString $+  spliceWith (\n -> showSigned (showIntAtBase b showDigit) 0 n "")++-- | Show an integral value in hexadecimal.+hex :: (Integral t, Show t, Monoid s, IsString s) => Format s a (t -> a)+hex = generalizeString $+  spliceWith (\n -> showSigned showHex 0 n "")++-- | Show an integral value in octal.+oct :: (Integral t, Show t, Monoid s, IsString s) => Format s a (t -> a)+oct = generalizeString $+  spliceWith (\n -> showSigned showOct 0 n "")++-- | Show a floating point value in exponential format. (e.g. 2.45e2, -1.5e-3)+-- If `digs` is Nothing, the value is shown to full precision, if it is Just d then at most+-- d digits after the decimal point are shown.+eFloat :: (RealFloat t, Monoid s, IsString s) => Maybe Int -> Format s a (t -> a)+eFloat digs = generalizeString $ spliceWith (\n -> showEFloat digs n "")++-- | Show a floating point value in standard decimal format. (e.g. 245000, -0.0015)+-- If `digs` is Nothing, the value is shown to full precision, if it is Just d then at most+-- d digits after the decimal point are shown.+fFloat :: (RealFloat t, Monoid s, IsString s) => Maybe Int -> Format s a (t -> a)+fFloat digs = generalizeString $ spliceWith (\n -> showFFloat digs n "")++-- | Show a floating point value using standard decimal notation for arguments whose absolute+-- value lies between 0.1 and 9,999,999, and scientific notation otherwise. +-- If `digs` is Nothing, the value is shown to full precision, if it is Just d then at most+-- d digits after the decimal point are shown.+gFloat :: (RealFloat t, Monoid s, IsString s) => Maybe Int -> Format s a (t -> a)+gFloat digs = generalizeString $ spliceWith (\n -> showGFloat digs n "")++-- | We can use `arr` from the Arrow instance for Cokleisli w to produce formatters+-- that manipulate the stack without printing. That is, we have+-- +-- > arr :: (Monoid m) => (s -> s') -> Format m s s'++-- | Push an argument onto the stack to be consumed by subsequent formatters.+push :: Monoid m => t -> Format m (t -> a) a+push x = arr (\k -> k x)++-- | Duplicate an argument on the stack, making it available twice.+dup :: Monoid m => Format m (t -> t -> a) (t -> a)+dup = arr (\k x -> k x x)++-- | Swap the next two arguments on the stack.+swap :: Monoid m => Format m (t -> t' -> a) (t' -> t -> a)+swap = arr (\k x y -> k y x)++-- | Skip the next argument on the stack.+skip :: Monoid m => Format m (t -> a) (t' -> t -> a)+skip = arr (\k x -> k)++-- | Apply a function to the argument on the top of the stack.+apply :: Monoid m => (u -> v) -> Format m (v -> a) (u -> a)+apply f = arr (\k x -> k (f x))++-- | Apply a binary function to the top two arguments on the stack.+apply2 :: Monoid m => (u -> v -> w) -> Format m (w -> a) (u -> v -> a)+apply2 f = arr (\k x y -> k (f x y))+
+ src/Control/Category/Printf/ByteString/Lazy.hs view
@@ -0,0 +1,28 @@+module Control.Category.Printf.ByteString.Lazy+       ( module Control.Category.Printf+       , printf+       , printfLn+       , hPrintf+       , hPrintfLn+       ) where++import Prelude hiding (id, (.))+import Control.Comonad+import Control.Category.Printf+import Data.ByteString.Lazy (ByteString)+import qualified Data.ByteString.Lazy as B+import qualified Data.ByteString.Lazy.Char8 as BC+import System.IO (Handle)++printf :: Format ByteString (IO ()) b -> b+printf = printfWith B.putStr++printfLn :: Format ByteString (IO ()) b -> b+printfLn = printfWith BC.putStrLn ++hPrintf :: Handle -> Format ByteString (IO ()) b -> b+hPrintf h = printfWith (B.hPutStr h)++hPrintfLn :: Handle -> Format ByteString (IO ()) b -> b+hPrintfLn h = printfWith (BC.hPutStrLn h)+
+ src/Control/Category/Printf/ByteString/Strict.hs view
@@ -0,0 +1,28 @@+module Control.Category.Printf.ByteString.Strict+       ( module Control.Category.Printf+       , printf+       , printfLn+       , hPrintf+       , hPrintfLn+       ) where++import Prelude hiding (id, (.))+import Control.Comonad+import Control.Category.Printf+import Data.ByteString (ByteString)+import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as BC+import System.IO (Handle)++printf :: Format ByteString (IO ()) b -> b+printf = printfWith B.putStr++printfLn :: Format ByteString (IO ()) b -> b+printfLn = printfWith BC.putStrLn ++hPrintf :: Handle -> Format ByteString (IO ()) b -> b+hPrintf h = printfWith (B.hPutStr h)++hPrintfLn :: Handle -> Format ByteString (IO ()) b -> b+hPrintfLn h = printfWith (BC.hPutStrLn h)+
+ src/Control/Category/Printf/String.hs view
@@ -0,0 +1,23 @@+module Control.Category.Printf.String +       (module Control.Category.Printf+       , printf+       , printfLn+       , hPrintf+       , hPrintfLn+       ) where++import Control.Comonad+import Control.Category.Printf+import System.IO (Handle, hPutStr, hPutStrLn)++printf :: Format String (IO ()) b -> b+printf = printfWith putStr++printfLn :: Format String (IO ()) b -> b+printfLn = printfWith putStrLn++hPrintf :: Handle -> Format String (IO ()) b -> b+hPrintf h = printfWith (hPutStr h)++hPrintfLn :: Handle -> Format String (IO ()) b -> b+hPrintfLn h = printfWith (hPutStrLn h)
+ src/Control/Category/Printf/Text/Lazy.hs view
@@ -0,0 +1,26 @@+module Control.Category.Printf.Text.Lazy+       ( module Control.Category.Printf+       , printf+       , printfLn+       , hPrintf+       , hPrintfLn+       ) where++import Prelude hiding (id, (.))+import Control.Comonad+import Control.Category.Printf+import Data.Text.Lazy (Text)+import qualified Data.Text.Lazy.IO as T+import System.IO (Handle)++printf :: Format Text (IO ()) b -> b+printf = printfWith T.putStr++printfLn :: Format Text (IO ()) b -> b+printfLn = printfWith T.putStrLn ++hPrintf :: Handle -> Format Text (IO ()) b -> b+hPrintf h = printfWith (T.hPutStr h)++hPrintfLn :: Handle -> Format Text (IO ()) b -> b+hPrintfLn h = printfWith (T.hPutStrLn h)
+ src/Control/Category/Printf/Text/Strict.hs view
@@ -0,0 +1,26 @@+module Control.Category.Printf.Text.Strict+       ( module Control.Category.Printf+       , printf+       , printfLn+       , hPrintf+       , hPrintfLn+       ) where++import Prelude hiding (id, (.))+import Control.Comonad+import Control.Category.Printf+import Data.Text (Text)+import qualified Data.Text.IO as T+import System.IO (Handle)++printf :: Format Text (IO ()) b -> b+printf = printfWith T.putStr++printfLn :: Format Text (IO ()) b -> b+printfLn = printfWith T.putStrLn ++hPrintf :: Handle -> Format Text (IO ()) b -> b+hPrintf h = printfWith (T.hPutStr h)++hPrintfLn :: Handle -> Format Text (IO ()) b -> b+hPrintfLn h = printfWith (T.hPutStrLn h)