total 1.0.3 → 1.0.4
raw patch · 4 files changed
+218/−219 lines, 4 filesdep −ghc-primsetup-changed
Dependencies removed: ghc-prim
Files
- LICENSE +24/−24
- Setup.hs +2/−2
- src/Lens/Family/Total.hs +166/−166
- total.cabal +26/−27
LICENSE view
@@ -1,24 +1,24 @@-Copyright (c) 2015 Gabriel Gonzalez -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 Gabriel Gonzalez 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. +Copyright (c) 2015 Gabriel Gonzalez+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 Gabriel Gonzalez 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
@@ -1,2 +1,2 @@-import Distribution.Simple -main = defaultMain +import Distribution.Simple+main = defaultMain
src/Lens/Family/Total.hs view
@@ -1,166 +1,166 @@-{-# LANGUAGE DefaultSignatures #-} -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE TypeOperators #-} - --- | This module lets you exhaustively pattern match on types using --- `Lens.Family.Lens`es, `Lens.Family.Traversal`s, or `Lens.Family.Prism`s. --- --- Here's an example use of this library: --- --- > import Lens.Family.Total --- > import Lens.Family.Stock --- > --- > total :: Either Char Int -> String -- Same as: --- > total = _case -- total = \case --- > & on _Left (\c -> replicate 3 c ) -- Left c -> replicate 3 c --- > & on _Right (\n -> replicate n '!') -- Right n -> replicate n '!' --- --- Our @total@ function pattern matches exhaustively on the `Either` type using --- the `Lens.Family.Stock._Left` and `Lens.Family.Stock._Right` prisms: --- --- >>> total (Left 'X') --- "XXX" --- >>> total (Right 2) --- "!!" --- --- The types ensure that the above function is total. For example, if you omit --- the `Lens.Family.Stock._Right` branch: --- --- > partial :: Either Char Int -> String --- > partial = _case --- > & on _Left (\c -> replicate 3 c ) --- --- ... then you will get the following type error: --- --- > No instance for (Empty Int) arising from a use of ‘_case’ --- > In the first argument of ‘(&)’, namely ‘_case’ --- > In the expression: _case & on _Left (\ c -> replicate 3 c) --- > In an equation for ‘partial’: --- > partial = _case & on _Left (\ c -> replicate 3 c) --- --- That type error means that you didn't pattern match on the branch with the --- `Int`. --- --- You can also implement exhaustive pattern matching for your own data types with --- `Lens.Family.Traversal`s or `Control.Lens.Prism`s. However, this only works if --- you have one type variable for each branch of your type: --- --- > {-# LANGUAGE DeriveGeneric #-} --- > {-# LANGUAGE TemplateHaskell #-} --- > --- > import Control.Lens.TH --- > import GHC.Generics (Generic) --- > import Lens.Family.Total --- > --- > data Example a b c = C1 a | C2 b | C3 c deriving (Generic) --- > --- > makePrisms ''Example --- > --- > instance (Empty a, Empty b, Empty c) => Empty (Example a b c) --- > --- > example :: Example String Char Int -> String -- Same as: --- > example = _case -- example = \case --- > & on _C1 (\s -> s ) -- C1 s -> s --- > & on _C2 (\c -> replicate 3 c ) -- C2 c -> replicate 3 c --- > & on _C3 (\n -> replicate n '!') -- C3 n -> replicate n '!' --- --- There is no way to prove that the pattern match is exhaustive unless there is --- a type parameter for every branch. This is because each successive pattern --- match `Void`s out that branch's type parameter to prove that the branch no --- longer needs to be handled. `_case` just verifies that all type parameters are --- `Void`. --- --- You can still write an inexhaustive pattern match so long as you provide a --- default: --- --- > example :: Example Int String Float -> String --- > example = _default "default" --- > & on _C2 (\s -> s) --- --- You can even pattern match using `Lens.Family.Lens`es, too: --- --- > example :: (Int, Char) -> String -- Same as: --- > example = _case -- example = \case --- > & on _1 (\n -> replicate n '1') -- (n, _) -> replicate n '1' --- --- ... and of course the identity lens (`id`) works, too: --- --- > example :: (Int, Char) -> String -- Same as: --- > example = _case -- example = \case --- > & on id (\(n, c) -> replicate n c) -- (n, c) -> replicate n c - -module Lens.Family.Total ( - Empty(..) - , _case - , _default - , on - , (&) - - -- * Re-exports - , Void - ) where - -import Data.Void (Void, absurd) -import GHC.Generics - --- | A type class for uninhabited types -class Empty a where - impossible :: a -> x - - default impossible :: (Generic a, GEmpty (Rep a)) => a -> x - impossible = gimpossible . from - -instance Empty Void where - impossible = absurd - -instance (Empty a, Empty b) => Empty (Either a b) where - impossible (Left a) = impossible a - impossible (Right b) = impossible b - -instance Empty a => Empty ((,) a b) where - impossible (a, _) = impossible a - -class GEmpty f where - gimpossible :: f a -> x - -instance GEmpty V1 where - gimpossible _ = undefined - -instance (GEmpty a, GEmpty b) => GEmpty (a :+: b) where - gimpossible (L1 l) = gimpossible l - gimpossible (R1 r) = gimpossible r - -instance Empty a => GEmpty (K1 i a) where - gimpossible (K1 k) = impossible k - -instance GEmpty a => GEmpty (M1 i c a) where - gimpossible (M1 m) = gimpossible m - -instance GEmpty a => GEmpty (a :*: b) where - gimpossible (a :*: _) = gimpossible a - --- | Synonym for `impossible`, used to check if a pattern match is exhaustive -_case :: Empty a => a -> x -_case = impossible - --- | Synonym for `const`, used to provide a default if a pattern match is --- inexhaustive -_default :: x -> a -> x -_default x _ = x - --- | Pattern match on a `Lens.Family.Traversal` -on - :: ((a -> Either a Void) -> i -> Either l r) - -> (l -> o) - -> (r -> o) - -> i - -> o -on p f g x = case p Left x of - Left l -> f l - Right r -> g r - --- | Operator for post-fix function application -(&) :: a -> (a -> b) -> b -x & f = f x - -infixl 1 & +{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeOperators #-}++-- | This module lets you exhaustively pattern match on types using+-- `Lens.Family.Lens`es, `Lens.Family.Traversal`s, or `Lens.Family.Prism`s.+--+-- Here's an example use of this library:+--+-- > import Lens.Family.Total+-- > import Lens.Family.Stock+-- >+-- > total :: Either Char Int -> String -- Same as:+-- > total = _case -- total = \case+-- > & on _Left (\c -> replicate 3 c ) -- Left c -> replicate 3 c+-- > & on _Right (\n -> replicate n '!') -- Right n -> replicate n '!'+--+-- Our @total@ function pattern matches exhaustively on the `Either` type using+-- the `Lens.Family.Stock._Left` and `Lens.Family.Stock._Right` prisms:+--+-- >>> total (Left 'X')+-- "XXX"+-- >>> total (Right 2)+-- "!!"+--+-- The types ensure that the above function is total. For example, if you omit+-- the `Lens.Family.Stock._Right` branch:+--+-- > partial :: Either Char Int -> String+-- > partial = _case+-- > & on _Left (\c -> replicate 3 c )+--+-- ... then you will get the following type error:+--+-- > No instance for (Empty Int) arising from a use of ‘_case’+-- > In the first argument of ‘(&)’, namely ‘_case’+-- > In the expression: _case & on _Left (\ c -> replicate 3 c)+-- > In an equation for ‘partial’:+-- > partial = _case & on _Left (\ c -> replicate 3 c)+--+-- That type error means that you didn't pattern match on the branch with the+-- `Int`.+--+-- You can also implement exhaustive pattern matching for your own data types with+-- `Lens.Family.Traversal`s or `Control.Lens.Prism`s. However, this only works if+-- you have one type variable for each branch of your type:+--+-- > {-# LANGUAGE DeriveGeneric #-}+-- > {-# LANGUAGE TemplateHaskell #-}+-- >+-- > import Control.Lens.TH+-- > import GHC.Generics (Generic)+-- > import Lens.Family.Total+-- >+-- > data Example a b c = C1 a | C2 b | C3 c deriving (Generic)+-- >+-- > makePrisms ''Example+-- >+-- > instance (Empty a, Empty b, Empty c) => Empty (Example a b c)+-- >+-- > example :: Example String Char Int -> String -- Same as:+-- > example = _case -- example = \case+-- > & on _C1 (\s -> s ) -- C1 s -> s+-- > & on _C2 (\c -> replicate 3 c ) -- C2 c -> replicate 3 c+-- > & on _C3 (\n -> replicate n '!') -- C3 n -> replicate n '!'+--+-- There is no way to prove that the pattern match is exhaustive unless there is+-- a type parameter for every branch. This is because each successive pattern+-- match `Void`s out that branch's type parameter to prove that the branch no+-- longer needs to be handled. `_case` just verifies that all type parameters are+-- `Void`.+--+-- You can still write an inexhaustive pattern match so long as you provide a+-- default:+--+-- > example :: Example Int String Float -> String+-- > example = _default "default"+-- > & on _C2 (\s -> s)+--+-- You can even pattern match using `Lens.Family.Lens`es, too:+--+-- > example :: (Int, Char) -> String -- Same as:+-- > example = _case -- example = \case+-- > & on _1 (\n -> replicate n '1') -- (n, _) -> replicate n '1'+--+-- ... and of course the identity lens (`id`) works, too:+--+-- > example :: (Int, Char) -> String -- Same as:+-- > example = _case -- example = \case+-- > & on id (\(n, c) -> replicate n c) -- (n, c) -> replicate n c++module Lens.Family.Total (+ Empty(..)+ , _case+ , _default+ , on+ , (&)++ -- * Re-exports+ , Void+ ) where++import Data.Void (Void, absurd)+import GHC.Generics++-- | A type class for uninhabited types+class Empty a where+ impossible :: a -> x++ default impossible :: (Generic a, GEmpty (Rep a)) => a -> x+ impossible = gimpossible . from++instance Empty Void where+ impossible = absurd++instance (Empty a, Empty b) => Empty (Either a b) where+ impossible (Left a) = impossible a+ impossible (Right b) = impossible b++instance Empty a => Empty ((,) a b) where+ impossible (a, _) = impossible a++class GEmpty f where+ gimpossible :: f a -> x++instance GEmpty V1 where+ gimpossible _ = undefined++instance (GEmpty a, GEmpty b) => GEmpty (a :+: b) where+ gimpossible (L1 l) = gimpossible l+ gimpossible (R1 r) = gimpossible r++instance Empty a => GEmpty (K1 i a) where+ gimpossible (K1 k) = impossible k++instance GEmpty a => GEmpty (M1 i c a) where+ gimpossible (M1 m) = gimpossible m++instance GEmpty a => GEmpty (a :*: b) where+ gimpossible (a :*: _) = gimpossible a++-- | Synonym for `impossible`, used to check if a pattern match is exhaustive+_case :: Empty a => a -> x+_case = impossible++-- | Synonym for `const`, used to provide a default if a pattern match is+-- inexhaustive+_default :: x -> a -> x+_default x _ = x++-- | Pattern match on a `Lens.Family.Traversal`+on+ :: ((a -> Either a Void) -> i -> Either l r)+ -> (l -> o)+ -> (r -> o)+ -> i+ -> o+on p f g x = case p Left x of+ Left l -> f l+ Right r -> g r++-- | Operator for post-fix function application+(&) :: a -> (a -> b) -> b+x & f = f x++infixl 1 &
total.cabal view
@@ -1,27 +1,26 @@-Name: total -Version: 1.0.3 -Cabal-Version: >=1.8.0.2 -Build-Type: Simple -License: BSD3 -License-File: LICENSE -Copyright: 2015 Gabriel Gonzalez -Author: Gabriel Gonzalez -Maintainer: Gabriel439@gmail.com -Bug-Reports: https://github.com/Gabriel439/Haskell-Total-Library/issues -Synopsis: Exhaustive pattern matching using lenses, traversals, and prisms -Description: Use this library if you wish to hide your data type's internal - representation while still providing a way to exhaustively pattern match on - your type using exposed lenses, traversals, or prisms. -Category: Control -Source-Repository head - Type: git - Location: https://github.com/Gabriel439/Haskell-Total-Library - -Library - Hs-Source-Dirs: src - Build-Depends: - base >= 4 && < 4.9, - ghc-prim >= 0.2.0.0 && < 0.4, - void >= 0.4 && < 0.8 - Exposed-Modules: Lens.Family.Total - GHC-Options: -O2 -Wall +Name: total+Version: 1.0.4+Cabal-Version: >=1.8.0.2+Build-Type: Simple+License: BSD3+License-File: LICENSE+Copyright: 2015 Gabriel Gonzalez+Author: Gabriel Gonzalez+Maintainer: Gabriel439@gmail.com+Bug-Reports: https://github.com/Gabriel439/Haskell-Total-Library/issues+Synopsis: Exhaustive pattern matching using lenses, traversals, and prisms+Description: Use this library if you wish to hide your data type's internal+ representation while still providing a way to exhaustively pattern match on+ your type using exposed lenses, traversals, or prisms.+Category: Control+Source-Repository head+ Type: git+ Location: https://github.com/Gabriel439/Haskell-Total-Library++Library+ Hs-Source-Dirs: src+ Build-Depends:+ base >= 4 && < 4.9,+ void >= 0.4 && < 0.8+ Exposed-Modules: Lens.Family.Total+ GHC-Options: -O2 -Wall