packages feed

arity-generic-liftA (empty) → 0.1.0.0

raw patch · 7 files changed

+202/−0 lines, 7 filesdep +arity-generic-liftAdep +basedep +doctestsetup-changed

Dependencies added: arity-generic-liftA, base, doctest

Files

+ LICENSE view
@@ -0,0 +1,21 @@+MIT License++Copyright (c) 2018 Donnacha Oisín Kidney++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.
+ README.md view
@@ -0,0 +1,15 @@+# arity-generic-liftA++There's a family of functions in+[Control.Applicative](https://hackage.haskell.org/package/base-4.11.0.0/docs/Control-Applicative.html)+which follow the pattern `liftA2`, `liftA3`, etc. Using some+tricks from Richard Eisenberg's thesis we can write them all at once. This+package does exactly that, providing a function (`lift`) which is an+arity-generic version of the `liftAn`.++```haskell+>>> lift (\x y z -> x ++ y ++ z) (Just "a") (Just "b") (Just "c")+Just "abc"+```++[Eisenberg, Richard A. “Dependent Types in Haskell: Theory and Practice.” University of Pennsylvania, 2016.](https://github.com/goldfirere/thesis/raw/master/built/thesis.pdf)
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ arity-generic-liftA.cabal view
@@ -0,0 +1,52 @@+-- This file has been generated from package.yaml by hpack version 0.28.2.+--+-- see: https://github.com/sol/hpack+--+-- hash: a5291f7acc496b8e14741d59cc33eeb92e35c60db728f80aae2427f87c8d690e++name:           arity-generic-liftA+version:        0.1.0.0+synopsis:       Provides an arity-generic version of the liftA2, liftA3... liftAn functions.+description:    Please see the README on GitHub at <https://github.com/oisdk/arity-generic-liftA#readme>+category:       Control+homepage:       https://github.com/oisdk/arity-generic-liftA#readme+bug-reports:    https://github.com/oisdk/arity-generic-liftA/issues+author:         Donnacha Oisín Kidney+maintainer:     mail@doisinkidney.com+copyright:      2018 Donnacha Oisín Kidney+license:        MIT+license-file:   LICENSE+build-type:     Simple+cabal-version:  >= 1.10+extra-source-files:+    README.md++source-repository head+  type: git+  location: https://github.com/oisdk/arity-generic-liftA++library+  exposed-modules:+      Control.Applicative.Lift+      Control.Applicative.Lift.Internal+  other-modules:+      Paths_arity_generic_liftA+  hs-source-dirs:+      src+  build-depends:+      base >=4.7 && <5+  default-language: Haskell2010++test-suite arity-generic-liftA-test+  type: exitcode-stdio-1.0+  main-is: Spec.hs+  other-modules:+      Paths_arity_generic_liftA+  hs-source-dirs:+      test+  ghc-options: -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      arity-generic-liftA+    , base >=4.7 && <5+    , doctest >=0.3.0+  default-language: Haskell2010
+ src/Control/Applicative/Lift.hs view
@@ -0,0 +1,24 @@+-- |+-- Module      : Control.Applicative.Lift+-- Copyright   : (c) Donnacha Oisín Kidney 2018+-- License     : MIT+-- Maintainer  : mail@doisinkidney.com+-- Portability : GHC+--+-- There's a family of functions in "Control.Applicative" which follow the+-- pattern 'Control.Applicative.liftA2', 'Control.Applicative.liftA3', etc.+-- Using some tricks from Richard Eisenberg's thesis we can write them all at+-- once.+--+--     * Eisenberg, Richard A. \"Dependent Types in Haskell: Theory and+--       Practice.\" University of Pennsylvania, 2016.+--       <https://github.com/goldfirere/thesis/raw/master/built/thesis.pdf>+--+-- This module exports the one 'lift' function; for the internal+-- implementation details see "Control.Applicative.Lift.Internal".++module Control.Applicative.Lift+  (lift)+  where++import           Control.Applicative.Lift.Internal (lift)
+ src/Control/Applicative/Lift/Internal.hs view
@@ -0,0 +1,84 @@+{-# LANGUAGE DataKinds             #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies          #-}++{-# OPTIONS_GHC -fno-warn-unticked-promoted-constructors #-}+{-# OPTIONS_HADDOCK not-home #-}++-- |+-- Module      : Control.Applicative.Lift.Internal+-- Copyright   : (c) Donnacha Oisín Kidney 2018+-- License     : MIT+-- Maintainer  : mail@doisinkidney.com+-- Portability : GHC+--+-- There's a family of functions in "Control.Applicative" which follow the+-- pattern 'Control.Applicative.liftA2', 'Control.Applicative.liftA3', etc.+-- Using some tricks from Richard Eisenberg's thesis we can write them all at+-- once.+--+--     * Eisenberg, Richard A. \"Dependent Types in Haskell: Theory and+--       Practice.\" University of Pennsylvania, 2016.+--       <https://github.com/goldfirere/thesis/raw/master/built/thesis.pdf>+module Control.Applicative.Lift.Internal where++-- | Simple implementation of Peano numbers.+data N = Z | S N++-- | @'AppFunc' f n a@ returns the type of the function @a@ "lifted" over @n@+-- arguments.+type family AppFunc f n a where+  AppFunc f Z a = f a+  AppFunc f (S n) (a -> b) = f a -> AppFunc f n b++-- | Counts the arguments of a function+type family CountArgs f where+  CountArgs (_ -> b) = S (CountArgs b)+  CountArgs _ = Z++-- | The actual class which constructs the lifted function.+class (CountArgs a ~ n) => Applyable a n where+  apply :: Applicative f => f a -> AppFunc f (CountArgs a) a++instance (CountArgs a ~ Z) => Applyable a Z where+  apply = id+  {-# INLINE apply #-}++instance Applyable b n => Applyable (a -> b) (S n) where+  apply f x = apply (f <*> x)+  {-# INLINE apply #-}++-- | Lift a function over applicative arguments. This function is an+-- arity-generic version of the functions 'Control.Applicative.liftA2',+-- 'Control.Applicative.liftA3', etc.+--+-- Type inference works best when the function being lifted is+-- monomorphic:+--+-- >>> lift (\x y z -> x ++ y ++ z) (Just "a") (Just "b") (Just "c")+-- Just "abc"+--+-- In these cases, GHC can see the number of arguments the function must+-- have, and so is able to pick the correct instance for 'Applyable'.+--+-- If the function is not monomorphic (for instance '+'), you will need+-- to give a type signature:+--+-- >>> lift ((+) :: Int -> Int -> Int) (Just 1) (Just 2)+-- Just 3+--+-- Alternatively, you can use type applications to monomorphise the+-- function:+--+-- >>> :set -XTypeApplications+-- >>> lift ((+) @Int) (Just 1) (Just 2)+-- Just 3+--+-- Finally, everything is aggressively inlined, so there should be no+-- cost to using this function over manually writing+-- 'Control.Applicative.liftA3' etc.+lift :: (Applyable b n, Applicative f) => (a -> b) -> (f a -> AppFunc f n b)+lift f x = apply (fmap f x)+{-# INLINE lift #-}
+ test/Spec.hs view
@@ -0,0 +1,4 @@+import Test.DocTest++main :: IO ()+main = doctest ["-isrc", "src/"]