-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Define Product and Sum as CMonoids * Define reduce for bags * Rename reduce function for bags * Define keys for finite map * Define Maybe as a PointedSet * Add some tests for () Key instance * Fix index test case * Add test cases for () key map unindex * Comment reduceBag * Add test for reduce * Fix spellings
- Loading branch information
Showing
9 changed files
with
143 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,9 @@ | ||
module Data.CMonoid where | ||
|
||
import Data.Monoid | ||
|
||
class Monoid a => CMonoid a | ||
-- (<>) is commutative | ||
-- (<>) is commutative | ||
|
||
instance Num k => CMonoid (Sum k) | ||
instance Num k => CMonoid (Product k) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
{-# LANGUAGE TypeFamilies #-} | ||
{-# LANGUAGE FlexibleContexts #-} | ||
{-# LANGUAGE FlexibleInstances #-} | ||
|
||
module Data.Key where | ||
|
||
import Data.PointedSet | ||
import Data.Bag | ||
import Data.CMonoid | ||
|
||
class (Functor (Map k)) => Key k where | ||
data Map k :: * -> * | ||
empty :: (PointedSet v) => Map k v | ||
isEmpty :: (PointedSet v) => Map k v -> Bool | ||
single :: (PointedSet v) => (k, v) -> Map k v | ||
merge :: (Map k v1, Map k v2) -> Map k (v1, v2) | ||
unmerge :: Map k (v1, v2) -> (Map k v1, Map k v2) | ||
unmerge x = (fmap fst x, fmap snd x) | ||
dom :: (PointedSet v) => Map k v -> Bag k | ||
cod :: (PointedSet v) => Map k v -> Bag v | ||
cod t = reduce (fmap return t) | ||
lookup :: Map k v -> (k -> v) | ||
index :: Bag (k, v) -> Map k (Bag v) | ||
unindex :: Map k (Bag v) -> Bag (k, v) | ||
reduce :: (PointedSet v, CMonoid v) => Map k v -> v | ||
reduce = reduceBag . cod | ||
|
||
instance Key () where | ||
newtype Map () v = Lone v deriving (Show, Eq) | ||
|
||
empty = Lone Data.PointedSet.null | ||
isEmpty (Lone v) = isNull v | ||
single ((), v) = Lone v | ||
merge (Lone v1, Lone v2) = Lone (v1, v2) | ||
dom map = if isEmpty map then Data.Bag.empty else pure () | ||
cod (Lone v) = if isEmpty (Lone v) then Data.Bag.empty else pure v | ||
lookup (Lone v) () = v | ||
index kvps = Lone (fmap snd kvps) | ||
unindex (Lone vs) = fmap (\v -> ((), v)) vs | ||
|
||
instance Functor (Map ()) where | ||
fmap f (Lone v) = Lone (f v) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,11 @@ | ||
module Data.PointedSet where | ||
|
||
import Data.Maybe | ||
|
||
class PointedSet a where | ||
null :: a | ||
isNull :: a -> Bool | ||
|
||
instance PointedSet (Maybe a) where | ||
null = Nothing | ||
isNull = isNothing |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
module Data.CMonoidSpec (spec) where | ||
|
||
import Test.Hspec | ||
import Data.Monoid | ||
|
||
spec :: Spec | ||
spec = do | ||
describe "CMonoid instance of Sum k" $ do | ||
it "is commutative" $ do | ||
(3 :: Sum Int) <> (5 :: Sum Int) `shouldBe` (5 :: Sum Int) <> (3 :: Sum Int) | ||
|
||
describe "CMonoid instance of Product k" $ do | ||
it "is commutative" $ do | ||
(13 :: Product Int) <> (23 :: Product Int) `shouldBe` (23 :: Product Int) <> (13 :: Product Int) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
module Data.KeySpec (spec) where | ||
|
||
import Test.Hspec | ||
import Data.Key | ||
import qualified Data.Bag as Bag | ||
import qualified Data.PointedSet as Pointed | ||
|
||
spec :: Spec | ||
spec = do | ||
describe "Data.Key ()" $ do | ||
it "returns Lone null for empty" $ do | ||
(empty :: Map () (Maybe Int)) `shouldBe` Lone Nothing | ||
it "can detect empty" $ do | ||
isEmpty (Lone Nothing :: Map () (Maybe Char)) `shouldBe` True | ||
it "does not incorrectly detect empty" $ do | ||
isEmpty (Lone (Just 'a') :: Map () (Maybe Char)) `shouldBe` False | ||
it "returns the correct single element for not null" $ do | ||
single ((), Just 3) `shouldBe` Lone (Just 3) | ||
it "returns the correct single element for null" $ do | ||
single ((), Nothing :: Maybe Int) `shouldBe` Lone (Nothing :: Maybe Int) | ||
it "can correctly merge two maps" $ do | ||
merge (Lone (Just 'b'), Lone (Just 'c')) `shouldBe` Lone (Just 'b', Just 'c') | ||
it "can correctly unmerge two maps" $ do | ||
unmerge (Lone (Just 3, Just 12)) `shouldBe` (Lone (Just 3), Lone (Just 12)) | ||
it "can correctly identify the domain of a non-empty map" $ do | ||
dom (Lone (Just 'e')) `shouldBe` Bag.Bag [()] | ||
it "can correctly identify the domain of an empty map" $ do | ||
dom (Lone (Nothing :: Maybe Int)) `shouldBe` Bag.empty | ||
it "can correctly identify the codomain of a non-empty map" $ do | ||
cod (Lone (Just 'e')) `shouldBe` Bag.Bag [Just 'e'] | ||
it "can correctly identify the codomain of an empty map" $ do | ||
cod (Lone (Nothing :: Maybe Bool)) `shouldBe` Bag.empty | ||
it "can lookup elements" $ do | ||
Data.Key.lookup (Lone (Just True)) () `shouldBe` Just True | ||
it "can index a bag of pairs without multiplicity of keys" $ do | ||
index (Bag.Bag [((), Just 'r')]) `shouldBe` Lone (Bag.Bag [Just 'r']) | ||
it "can index an empty bag, with PointedSet null value as the null bag" $ do | ||
index (Bag.empty :: Bag.Bag ((), Int)) `shouldBe` Lone (Pointed.null :: Bag.Bag Int) | ||
it "can index a bag of pairs with multiplicity" $ do | ||
index (Bag.Bag [((), 'a'), ((), 'b'), ((), 'c')]) `shouldBe` Lone (Bag.Bag ['a', 'b', 'c']) | ||
it "can unindex a map with no multiplicities" $ do | ||
unindex (Lone (Bag.Bag [1])) `shouldBe` Bag.Bag [((), 1)] | ||
it "can unindex an empty map" $ do | ||
unindex (Lone (Pointed.null :: Bag.Bag Char)) `shouldBe` (Bag.empty :: Bag.Bag ((), Char)) | ||
it "can unindex a map with multiplicities" $ do | ||
unindex (Lone (Bag.Bag [True, True, False])) `shouldBe` Bag.Bag [((), True), ((), True), ((), False)] | ||
it "can reduce a map correctly" $ do | ||
reduce (Lone (Bag.Bag ['a'])) `shouldBe` Bag.Bag ['a'] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
module Data.PointedSetSpec (spec) where | ||
|
||
import Test.Hspec | ||
import qualified Data.PointedSet as Pointed | ||
|
||
spec :: Spec | ||
spec = do | ||
describe "Maybe PointedSet" $ do | ||
it "has Nothing as its null value" $ do | ||
(Pointed.null :: Maybe Int) `shouldBe` Nothing | ||
it "correctly detects Nothing as null" $ do | ||
Pointed.isNull (Nothing :: Maybe Int) `shouldBe` True | ||
it "does not interpret Just as Null" $ do | ||
Pointed.isNull (Just 3) `shouldBe` False |