exotic-list-monads 1.1.1 → 1.2.0
raw patch · 6 files changed
+148/−17 lines, 6 files
Files
- CHANGELOG.md +11/−7
- README.md +1/−1
- exotic-list-monads.cabal +5/−6
- src/Control/Monad/List/Exotic.hs +0/−1
- src/Control/Monad/List/NonEmpty/Exotic.hs +70/−1
- test/Control/Monad/List/NonEmpty/ExoticSpec.hs +61/−1
CHANGELOG.md view
@@ -1,24 +1,28 @@ # exotic-list-monad changelog +## v1.2.0++- Add the `AlphaNOmegaK` monad+ ## v1.1.1 -- Refactor to avoid the noncanonical-monad-instances and star-is-type warnings+- Refactor to avoid the `noncanonical-monad-instances` and `star-is-type` warnings -- Add Eq and Show instances to DualListMonad+- Add `Eq` and `Show` instances to `DualListMonad` - Fixes in documentation ## v1.1.0 -- Add the AtMost monad+- Add the `AtMost` monad -- Add the NumericalMonoidMonad monad+- Add the `NumericalMonoidMonad` monad -- Fixed the documentation to make Mini and Odd instances of NumericalMonoidMonad+- Fixed the documentation to make `Mini` and `Odd` instances of `NumericalMonoidMonad` -- Add AtLeast as another instance of NumericalMonoidMonad+- Add `AtLeast` as another instance of `NumericalMonoidMonad` -- Add the ContinuumOfMonads construction+- Add the `ContinuumOfMonads` construction ## v1.0.1
README.md view
@@ -8,7 +8,7 @@ * [Degrading Lists](https://raw.githubusercontent.com/maciejpirog/exotic-list-monads/master/degrading-lists.pdf) by Dylan McDermott, Maciej Piróg, Tarmo Uustalu (PPDP 2020), -* [Counting Monads on Lists](https://cla.tcs.uj.edu.pl/pdfs/McDermott-Pirog-Uustalu-Abstract.pdf) by Dylan McDermott, Maciej Piróg, Tarmo Uustalu (CLA 2023),+* [Counting Monads on Lists](http://cla.tcs.uj.edu.pl/history/2023/pdfs/McDermott-Pirog-Uustalu-Abstract.pdf) by Dylan McDermott, Maciej Piróg, Tarmo Uustalu (CLA 2023), * [Hybrid Programs](http://alfa.di.uminho.pt/~nevrenato/pdfs/thesis.pdf) by Renato Neves (PhD Thesis, 2018).
exotic-list-monads.cabal view
@@ -1,13 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.33.0.+-- This file has been generated from package.yaml by hpack version 0.37.0. -- -- see: https://github.com/sol/hpack------ hash: 5b5385de8f22ca1f51a19de7b8b393b9012fded676d9ea7412ac96fde7fc9d83 name: exotic-list-monads-version: 1.1.1+version: 1.2.0 synopsis: Non-standard monads on lists and non-empty lists description: The usual list monad is only one of infinitely many ways to turn the list functor into a monad. The same applies to the usual non-empty list monad and the non-empty list functor. This library collects such non-standard "list" and "non-empty list" monads. category: List, Monads@@ -15,11 +13,12 @@ bug-reports: http://github.com/maciejpirog/exotic-list-monads/issues author: Maciej Piróg <maciej.adam.pirog@gmial.com> maintainer: Maciej Piróg <maciej.adam.pirog@gmail.com>-copyright: (c) 2020 Dylan McDermott, Maciej Piróg, Tarmo Uustalu+copyright: (c) 2020-2025 Dylan McDermott, Maciej Piróg, Tarmo Uustalu license: MIT license-file: LICENSE-tested-with: GHC ==8.0.2 || ==8.2.2 || ==8.4.4 || ==8.6.5 || ==8.8.3 || ==8.10.1 build-type: Simple+tested-with:+ GHC ==9.4.8 extra-source-files: README.md CHANGELOG.md
src/Control/Monad/List/Exotic.hs view
@@ -169,7 +169,6 @@ -- ** The Short Stutter-Keeper monad (?) , ShortStutterKeeper(..)- ) where import Prelude hiding ((<>))
src/Control/Monad/List/NonEmpty/Exotic.hs view
@@ -13,8 +13,10 @@ {-# LANGUAGE PolyKinds #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE PartialTypeSignatures #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE OverloadedLists #-} + -- {-# LANGUAGE OverloadedStrings #-} -- |@@ -144,6 +146,10 @@ , AlphaOmega(..) + -- ** The ΑⁿΩᵏ monad (?)++ , AlphaNOmegaK(..)+ -- * Constructions on non-empty monads -- ** The dual non-empty list monad@@ -172,7 +178,8 @@ import Control.Monad (ap, join) import Data.Kind (Type) import GHC.Exts (IsList(..), IsString(..), Constraint)-import GHC.TypeLits+-- import GHC.TypeLits+import GHC.TypeNats import Data.Proxy import qualified Data.Semigroup (Semigroup) import Control.Monad.List.Exotic (ListMonad, palindromize)@@ -863,6 +870,64 @@ instance IsString (AlphaOmega Char) where fromString = fromList +-----------------------+-- The Α^n-Ω^k monad --+-----------------------++-- | A generalisation of the ΑΩ monad in which we replicate the first element+-- @n@ times and the last element @k@ times. It is a monad when @n + k >= 2@.+--+-- @+-- join xss | isSingle xss || nonEmptyAll isSingle xss+-- = nonEmptyConcat xss+-- | otherwise+-- = fromList $+-- replicate n (NonEmpty.head $ NonEmpty.head xss) +++-- replicate k (NonEmpty.last $ NonEmpty.last xss)+-- @+--+-- For example:+--+-- >>> toList $ unwrap (join ["John", "Paul", "George", "Ringo"] :: AlphaOmega 2 3 Char)+-- "JJooo"+-- >>> toList $ unwrap (join ["John", "Paul", "George", "Ringo"] :: AlphaOmega 0 6 Char)+-- "oooooo"+newtype AlphaNOmegaK (n :: Nat) (k :: Nat) a = AlphaNOmegaK { unAlphaNOmegaK :: NonEmpty a }+ deriving (Functor, Show, Eq)++instance (KnownNat n, KnownNat k, 2 <= n + k) => Applicative (AlphaNOmegaK n k) where+ pure a = AlphaNOmegaK [a] -- OverloadedLists+ (<*>) = ap++instance (KnownNat n, KnownNat k, 2 <= n + k) => Monad (AlphaNOmegaK n k) where+ AlphaNOmegaK xs >>= f = AlphaNOmegaK $ join $ NonEmpty.map (unAlphaNOmegaK . f) xs+ where+ join xss | isSingle xss || nonEmptyAll isSingle xss+ = nonEmptyConcat xss+ | otherwise+ = let n = fromIntegral $ natVal (Proxy :: Proxy n)+ k = fromIntegral $ natVal (Proxy :: Proxy k)+ in fromList $+ replicate n (NonEmpty.head $ NonEmpty.head xss) +++ replicate k (NonEmpty.last $ NonEmpty.last xss)++instance (KnownNat n, KnownNat k, 2 <= n + k) => IsNonEmpty (AlphaNOmegaK n k a) where+ type ItemNE (AlphaNOmegaK n k a) = a+ fromNonEmpty = AlphaNOmegaK+ toNonEmpty = unAlphaNOmegaK++instance (KnownNat n, KnownNat k, 2 <= n + k) => NonEmptyMonad (AlphaNOmegaK n k)++instance (KnownNat n, KnownNat k, 2 <= n + k) => IsList (AlphaNOmegaK n k a) where+ type Item (AlphaNOmegaK n k a) = a+ fromList = fromNonEmpty . fromList+ toList = toList . toNonEmpty++-- The following is needed for the examples in the docs:++instance (KnownNat n, KnownNat k, 2 <= n + k) => IsString (AlphaNOmegaK n k Char) where+ fromString = fromList+ ------------------------------- -- Dual non-empty list monad -- -------------------------------@@ -960,6 +1025,8 @@ -- | (?) instance HasShortFront AlphaOmega +instance (KnownNat n, KnownNat k, 2 <= n + k) => HasShortFront (AlphaNOmegaK n k)+ instance (HasShortRear m) => HasShortFront (DualNonEmptyMonad m) -- | This is a transformer for a number of monads (instances of the@@ -1044,6 +1111,8 @@ -- | (?) instance HasShortRear AlphaOmega++instance (KnownNat n, KnownNat k, 2 <= n + k) => HasShortRear (AlphaNOmegaK n k) instance (HasShortFront m) => HasShortRear (DualNonEmptyMonad m)
test/Control/Monad/List/NonEmpty/ExoticSpec.hs view
@@ -45,6 +45,7 @@ deriving instance (Arbitrary a) => Arbitrary (HeadTails a) deriving instance (Arbitrary a) => Arbitrary (HeadsTail a) deriving instance (Arbitrary a) => Arbitrary (AlphaOmega a)+deriving instance (Arbitrary a) => Arbitrary (AlphaNOmegaK n k a) deriving instance (Arbitrary (m a)) => Arbitrary (ShortFront m 0 a) deriving instance (Arbitrary (m a)) => Arbitrary (ShortFront m 1 a) deriving instance (Arbitrary (m a)) => Arbitrary (ShortFront m 2 a)@@ -54,6 +55,9 @@ deriving instance (Arbitrary (m a)) => Arbitrary (ShortRear m 2 a) deriving instance (Arbitrary (m a)) => Arbitrary (ShortRear m 5 a) +assocTests :: Int+assocTests = 250+ testMonad :: forall m. (Monad m, Eq (m Int), Arbitrary (m Int), Arbitrary (m (m (m Int))), Show (m Int), Show (m (m (m Int))))@@ -64,7 +68,7 @@ \xs -> join (fmap return xs) == (xs :: m Int) it "right unit:" $ property $ \xs -> join (return xs) == (xs :: m Int)- modifyMaxSuccess (const 100) $ it "associativity:" $ property $+ modifyMaxSuccess (const assocTests) $ it "associativity:" $ property $ \xsss -> join (join xsss) == (join (fmap join xsss) :: m Int) spec :: Spec@@ -138,6 +142,20 @@ testMonad "AlphaOmega" (Proxy :: Proxy AlphaOmega) + testMonad "AlphaNOmegaK 1 1" (Proxy :: Proxy (AlphaNOmegaK 1 1))+ testMonad "AlphaNOmegaK 2 0" (Proxy :: Proxy (AlphaNOmegaK 2 0))+ testMonad "AlphaNOmegaK 0 2" (Proxy :: Proxy (AlphaNOmegaK 0 2))+ testMonad "AlphaNOmegaK 2 1" (Proxy :: Proxy (AlphaNOmegaK 2 1))+ testMonad "AlphaNOmegaK 1 2" (Proxy :: Proxy (AlphaNOmegaK 1 2))+ testMonad "AlphaNOmegaK 2 2" (Proxy :: Proxy (AlphaNOmegaK 2 2))+ testMonad "AlphaNOmegaK 3 1" (Proxy :: Proxy (AlphaNOmegaK 3 1))+ testMonad "AlphaNOmegaK 1 3" (Proxy :: Proxy (AlphaNOmegaK 1 3))+ testMonad "AlphaNOmegaK 3 2" (Proxy :: Proxy (AlphaNOmegaK 3 2))+ testMonad "AlphaNOmegaK 2 3" (Proxy :: Proxy (AlphaNOmegaK 2 3))+ testMonad "AlphaNOmegaK 3 3" (Proxy :: Proxy (AlphaNOmegaK 3 3))+ testMonad "AlphaNOmegaK 6 8" (Proxy :: Proxy (AlphaNOmegaK 6 8))+ testMonad "AlphaNOmegaK 9 3" (Proxy :: Proxy (AlphaNOmegaK 9 3))+ testMonad "ShortFront NonEmpty 0" (Proxy :: Proxy (ShortFront NonEmpty 0)) testMonad "ShortFront NonEmpty 1" (Proxy :: Proxy (ShortFront NonEmpty 1)) testMonad "ShortFront NonEmpty 2" (Proxy :: Proxy (ShortFront NonEmpty 2))@@ -183,6 +201,27 @@ testMonad "ShortFront AlphaOmega 2" (Proxy :: Proxy (ShortFront AlphaOmega 2)) testMonad "ShortFront AlphaOmega 5" (Proxy :: Proxy (ShortFront AlphaOmega 5)) + testMonad "ShortFront (AlphaNOmegaK 1 1) 0" (Proxy :: Proxy (ShortFront (AlphaNOmegaK 1 1) 0))+ testMonad "ShortFront (AlphaNOmegaK 1 1) 1" (Proxy :: Proxy (ShortFront (AlphaNOmegaK 1 1) 1))+ testMonad "ShortFront (AlphaNOmegaK 1 1) 2" (Proxy :: Proxy (ShortFront (AlphaNOmegaK 1 1) 2))+ testMonad "ShortFront (AlphaNOmegaK 1 1) 5" (Proxy :: Proxy (ShortFront (AlphaNOmegaK 1 1) 5))+ testMonad "ShortFront (AlphaNOmegaK 2 0) 0" (Proxy :: Proxy (ShortFront (AlphaNOmegaK 2 0) 0))+ testMonad "ShortFront (AlphaNOmegaK 2 0) 1" (Proxy :: Proxy (ShortFront (AlphaNOmegaK 2 0) 1))+ testMonad "ShortFront (AlphaNOmegaK 2 0) 2" (Proxy :: Proxy (ShortFront (AlphaNOmegaK 2 0) 2))+ testMonad "ShortFront (AlphaNOmegaK 2 0) 5" (Proxy :: Proxy (ShortFront (AlphaNOmegaK 2 0) 5))+ testMonad "ShortFront (AlphaNOmegaK 0 2) 0" (Proxy :: Proxy (ShortFront (AlphaNOmegaK 0 2) 0))+ testMonad "ShortFront (AlphaNOmegaK 0 2) 0" (Proxy :: Proxy (ShortFront (AlphaNOmegaK 0 2) 0))+ testMonad "ShortFront (AlphaNOmegaK 0 2) 1" (Proxy :: Proxy (ShortFront (AlphaNOmegaK 0 2) 1))+ testMonad "ShortFront (AlphaNOmegaK 0 2) 2" (Proxy :: Proxy (ShortFront (AlphaNOmegaK 0 2) 2))+ testMonad "ShortFront (AlphaNOmegaK 2 3) 5" (Proxy :: Proxy (ShortFront (AlphaNOmegaK 2 3) 5))+ testMonad "ShortFront (AlphaNOmegaK 2 3) 1" (Proxy :: Proxy (ShortFront (AlphaNOmegaK 2 3) 1))+ testMonad "ShortFront (AlphaNOmegaK 2 3) 2" (Proxy :: Proxy (ShortFront (AlphaNOmegaK 2 3) 2))+ testMonad "ShortFront (AlphaNOmegaK 2 3) 5" (Proxy :: Proxy (ShortFront (AlphaNOmegaK 2 3) 5))+ testMonad "ShortFront (AlphaNOmegaK 12 3) 5" (Proxy :: Proxy (ShortFront (AlphaNOmegaK 12 3) 5))+ testMonad "ShortFront (AlphaNOmegaK 12 3) 1" (Proxy :: Proxy (ShortFront (AlphaNOmegaK 12 3) 1))+ testMonad "ShortFront (AlphaNOmegaK 12 3) 2" (Proxy :: Proxy (ShortFront (AlphaNOmegaK 12 3) 2))+ testMonad "ShortFront (AlphaNOmegaK 12 3) 5" (Proxy :: Proxy (ShortFront (AlphaNOmegaK 12 3) 5))+ testMonad "ShortFront (DualNonEmptyMonad DiscreteHybridNE) 0" (Proxy :: Proxy (ShortFront (DualNonEmptyMonad DiscreteHybridNE) 0)) testMonad "ShortFront (DualNonEmptyMonad DiscreteHybridNE) 1" (Proxy :: Proxy (ShortFront (DualNonEmptyMonad DiscreteHybridNE) 1)) testMonad "ShortFront (DualNonEmptyMonad DiscreteHybridNE) 2" (Proxy :: Proxy (ShortFront (DualNonEmptyMonad DiscreteHybridNE) 2))@@ -202,6 +241,27 @@ testMonad "ShortRear AlphaOmega 1" (Proxy :: Proxy (ShortRear AlphaOmega 1)) testMonad "ShortRear AlphaOmega 2" (Proxy :: Proxy (ShortRear AlphaOmega 2)) testMonad "ShortRear AlphaOmega 5" (Proxy :: Proxy (ShortRear AlphaOmega 5))++ testMonad "ShortRear (AlphaNOmegaK 1 1) 0" (Proxy :: Proxy (ShortRear (AlphaNOmegaK 1 1) 0))+ testMonad "ShortRear (AlphaNOmegaK 1 1) 1" (Proxy :: Proxy (ShortRear (AlphaNOmegaK 1 1) 1))+ testMonad "ShortRear (AlphaNOmegaK 1 1) 2" (Proxy :: Proxy (ShortRear (AlphaNOmegaK 1 1) 2))+ testMonad "ShortRear (AlphaNOmegaK 1 1) 5" (Proxy :: Proxy (ShortRear (AlphaNOmegaK 1 1) 5))+ testMonad "ShortRear (AlphaNOmegaK 2 0) 0" (Proxy :: Proxy (ShortRear (AlphaNOmegaK 2 0) 0))+ testMonad "ShortRear (AlphaNOmegaK 2 0) 1" (Proxy :: Proxy (ShortRear (AlphaNOmegaK 2 0) 1))+ testMonad "ShortRear (AlphaNOmegaK 2 0) 2" (Proxy :: Proxy (ShortRear (AlphaNOmegaK 2 0) 2))+ testMonad "ShortRear (AlphaNOmegaK 2 0) 5" (Proxy :: Proxy (ShortRear (AlphaNOmegaK 2 0) 5))+ testMonad "ShortRear (AlphaNOmegaK 0 2) 0" (Proxy :: Proxy (ShortRear (AlphaNOmegaK 0 2) 0))+ testMonad "ShortRear (AlphaNOmegaK 0 2) 0" (Proxy :: Proxy (ShortRear (AlphaNOmegaK 0 2) 0))+ testMonad "ShortRear (AlphaNOmegaK 0 2) 1" (Proxy :: Proxy (ShortRear (AlphaNOmegaK 0 2) 1))+ testMonad "ShortRear (AlphaNOmegaK 0 2) 2" (Proxy :: Proxy (ShortRear (AlphaNOmegaK 0 2) 2))+ testMonad "ShortRear (AlphaNOmegaK 2 3) 5" (Proxy :: Proxy (ShortRear (AlphaNOmegaK 2 3) 5))+ testMonad "ShortRear (AlphaNOmegaK 2 3) 1" (Proxy :: Proxy (ShortRear (AlphaNOmegaK 2 3) 1))+ testMonad "ShortRear (AlphaNOmegaK 2 3) 2" (Proxy :: Proxy (ShortRear (AlphaNOmegaK 2 3) 2))+ testMonad "ShortRear (AlphaNOmegaK 2 3) 5" (Proxy :: Proxy (ShortRear (AlphaNOmegaK 2 3) 5))+ testMonad "ShortRear (AlphaNOmegaK 12 3) 5" (Proxy :: Proxy (ShortRear (AlphaNOmegaK 12 3) 5))+ testMonad "ShortRear (AlphaNOmegaK 12 3) 1" (Proxy :: Proxy (ShortRear (AlphaNOmegaK 12 3) 1))+ testMonad "ShortRear (AlphaNOmegaK 12 3) 2" (Proxy :: Proxy (ShortRear (AlphaNOmegaK 12 3) 2))+ testMonad "ShortRear (AlphaNOmegaK 12 3) 5" (Proxy :: Proxy (ShortRear (AlphaNOmegaK 12 3) 5)) testMonad "ShortRear (DualNonEmptyMonad Keeper) 0" (Proxy :: Proxy (ShortRear (DualNonEmptyMonad Keeper) 0)) testMonad "ShortRear (DualNonEmptyMonad Keeper) 1" (Proxy :: Proxy (ShortRear (DualNonEmptyMonad Keeper) 1))