data-extend-generic (empty) → 0.1.0.0
raw patch · 6 files changed
+226/−0 lines, 6 filesdep +basedep +data-extend-genericdep +hspecsetup-changed
Dependencies added: base, data-extend-generic, hspec
Files
- LICENSE +30/−0
- Setup.hs +2/−0
- data-extend-generic.cabal +35/−0
- src/Data/Extend.hs +44/−0
- src/Data/Extend/Internal.hs +65/−0
- test/Spec.hs +50/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Author name here (c) 2015++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 Author name here 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
+ data-extend-generic.cabal view
@@ -0,0 +1,35 @@+name: data-extend-generic+version: 0.1.0.0+synopsis: Extend Haskell data or newtype like in OOP languages+description: This package allows you to extend Haskell data or newtype like in OOP languages.+homepage: http://github.com/githubuser/data-extend-generic#readme+license: BSD3+license-file: LICENSE+author: Yu Li+maintainer: ylilarry@gmail.com+copyright: 2010 Yu Li+category: Data+build-type: Simple+-- extra-source-files:+cabal-version: >=1.10++library+ hs-source-dirs: src+ exposed-modules: Data.Extend+ , Data.Extend.Internal+ build-depends: base >= 4.7 && < 5+ default-language: Haskell2010++test-suite data-extend-generic-test+ type: exitcode-stdio-1.0+ hs-source-dirs: test+ main-is: Spec.hs+ build-depends: base+ , data-extend-generic+ , hspec+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ default-language: Haskell2010++source-repository head+ type: git+ location: https://github.com/githubuser/data-extend-generic
+ src/Data/Extend.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE Safe #-}+----------------------------------------------------------------------------------+-- |+-- Module : Data.Extend+-- Copyright : (c) Yu Li, 2015+-- License : BSD+-- Maintainer : ylilarry@gmail.com+-- Stability : experimental+-- Portability : GHC extensions+--+-- This package allows you to extend a Haskell data like how you do in OOP.+--+-- Here is an example use for testing:+--+-- >+-- > data Test = Test | TestA {+-- > f1 :: Int,+-- > f2 :: Maybe Int,+-- > f3 :: Maybe Int+-- > } deriving (Show, Generic, Eq)+-- >+-- > test1A = TestA 1 (Just 1) (Just 3)+-- > test2A = TestA 0 Nothing (Just 2)+-- >+-- > main :: IO ()+-- > main = hspec $+-- > describe "Data.Extend" $ do+-- > specify "Int" $+-- > (2 `extend` 1) `shouldBe` (2 :: Int)+-- > specify "String" $+-- > ("b" `extend` "a") `shouldBe` "b"+-- > specify "data 0" $+-- > (Test `extend` Test) `shouldBe` Test+-- > specify "data 1" $+-- > (test2A `extend` test1A) `shouldBe` TestA 0 (Just 1) (Just 2)+-- >+--+----------------------------------------------------------------------------------++module Data.Extend (+ Extend(..)+ ) where++import Data.Extend.Internal
+ src/Data/Extend/Internal.hs view
@@ -0,0 +1,65 @@+{-# LANGUAGE Safe #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-}++module Data.Extend.Internal where++import Control.Applicative+import GHC.Generics+++class GExtend a where+ gExtend :: a p -> a p -> a p+++instance (GExtend (K1 i (m a)), Alternative m, GExtend b) => GExtend (K1 i (m a) :*: b) where+ gExtend (K1 a1 :*: b1) (K1 a2 :*: b2) = K1 (a1 <|> a2) :*: gExtend b1 b2++instance GExtend U1 where+ gExtend _ _ = U1++instance (Extend a) => GExtend (K1 i a) where+ gExtend (K1 a) (K1 b) = K1 $ extend a b++instance (GExtend a, GExtend b) => GExtend (a :*: b) where+ gExtend (a1 :*: b1) (a2 :*: b2) = gExtend a1 a2 :*: gExtend b1 b2++instance (GExtend a, GExtend b) => GExtend (a :+: b) where+ gExtend (L1 a) (L1 b) = L1 $ gExtend a b+ gExtend (R1 a) (R1 b) = R1 $ gExtend a b+ gExtend a _ = a++instance (GExtend a) => GExtend (M1 i c a) where+ gExtend (M1 a) (M1 b) = M1 $ gExtend a b+++class Extend a where+ -- | By default+ --+ -- prop> a `extend` b = a+ --+ -- prop> Nothing `extend` Just a = Just a+ --+ -- To use the "Extend" class, simply make your data derive Generic.+ --+ -- If "a" is a user defined data type, then all "Nothing" fields of "a" are replaced by corresponding fields in "b",+ --+ -- ie, all "Just" fields in "a" will override corresponding fields in "b".+ extend :: a -> a -> a+ default extend :: (Generic a, GExtend (Rep a)) => a -> a -> a+ extend a b = to $ gExtend (from a) (from b)+++instance (Extend a) => Extend (Maybe a) where+ -- | Nothing `extend` Just b = Just b+ -- (Just a) `extend` (Just b) = Just a+ extend (Just a) _ = Just a+ extend Nothing b = b++instance {-# OVERLAPPABLE #-} Extend a where+ -- | By default a `extend` b is a+ extend a _ = a+
+ test/Spec.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE DeriveGeneric #-}++import Test.Hspec+import Data.Extend+import GHC.Generics+++data Test = Test | TestA {+ f1 :: Int,+ f2 :: Maybe Int,+ f3 :: Maybe Int+ } | TestB {+ g1 :: Int,+ g2 :: Maybe Int,+ g3 :: Maybe Int+ } deriving (Show, Generic, Eq)++test1A = TestA 1 (Just 1) Nothing+test2A = TestA 0 Nothing (Just 2)++test1B = TestB 1 (Just 1) Nothing+test2B = TestB 0 Nothing (Just 2)++++instance Extend Test++main :: IO ()+main = hspec $+ describe "Data.Extend" $ do+ specify "Int" $+ (2 `extend` 1) `shouldBe` (2 :: Int)+ specify "String" $+ ("b" `extend` "a") `shouldBe` "b"+ specify "data 0" $+ (Test `extend` Test) `shouldBe` Test+ specify "data 1" $+ (test2A `extend` test1A) `shouldBe` TestA 0 (Just 1) (Just 2)+ specify "data 2" $+ (test2B `extend` test1B) `shouldBe` TestB 0 (Just 1) (Just 2)+ specify "data 3" $+ (test2B `extend` test1A) `shouldBe` test2B+ specify "data 4" $+ (test1A `extend` test2B) `shouldBe` test1A+ specify "data 5" $+ (test2A `extend` test1B) `shouldBe` test2A+ specify "data 6" $+ (test1B `extend` test2A) `shouldBe` test1B++