packages feed

railroad 0.1.1.3 → 0.1.1.4

raw patch · 5 files changed

+33/−24 lines, 5 filesdep ~effectfuldep ~validationPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: effectful, validation

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -1,5 +1,12 @@ # Revision history for railroad +## 0.1.1.4 -- 2026-10-10+* Widen dependency upper bounds (tests pass):+  - `effectful < 2.8`+  - `validation < 1.4`+* Stop using `Data.Validation.toEither`, which `validation-1.3` no longer exports.+* Declare `hspec-discover` as a `build-tool-depends` of the test suite, so the tests build outside the nix shell.+ ## 0.1.1.3 -- 2026-10-10 * Documentation fixes: correct "success" typo and the doc comment of `(?)` in `Railroad.MonadError`. 
railroad.cabal view
@@ -1,6 +1,6 @@ cabal-version:      3.0 name:               railroad-version:            0.1.1.3+version:            0.1.1.4 license:            BSD-3-Clause license-file:       LICENSE author:             Frederik Kallstrup Mastratisi@@ -22,9 +22,9 @@     ghc-options: -Wall     build-depends:       base >=4.17 && < 4.23,-      effectful >= 2.5 && < 2.7,+      effectful >= 2.5 && < 2.8,       mtl >= 2.2 && < 2.4,-      validation >= 1.1 && < 1.2+      validation >= 1.1 && < 1.4  library     import:           stuff@@ -42,6 +42,8 @@     main-is:          Main.hs     other-modules:    RailroadSpec                       Railroad.MonadErrorSpec+    build-tool-depends:+                  hspec-discover:hspec-discover >= 2.11.14 && < 2.12     build-depends:                   base  >=4.17 && < 4.23,                   hspec  >= 2.11.14 && < 2.12,
src/Railroad.hs view
@@ -9,7 +9,7 @@ import           Data.Bool               (bool) import           Data.Foldable           (toList) import           Data.Kind               (Type)-import           Data.Validation         (Validation, toEither)+import           Data.Validation         (Validation (..)) import           Effectful               (Eff, type (:>)) import           Effectful.Error.Dynamic (Error, throwError_) @@ -40,7 +40,9 @@   bifurcate = id   -- either :: (e -> b) -> (a -> b) -> Either e a -> b instance Bifurcate (Validation e a) where-  bifurcate = toEither+  bifurcate = \case+    Failure e -> Left e+    Success a -> Right a   -- validation :: (e -> b) -> (a -> b) -> Validation e a -> b  instance (Traversable t, CErr (t Bool) ~ (), CRes (t Bool) ~ t ())@@ -56,8 +58,7 @@   -- pedagogically: bifurcate = bifurcate . sequenceA instance (Traversable t, Semigroup e, CErr (t (Validation e a)) ~ e, CRes (t (Validation e a)) ~ t a)     => Bifurcate (t (Validation e a)) where-  bifurcate = toEither . sequenceA-  -- pedagogically: bifurcate = bifurcate . sequenceA+  bifurcate = bifurcate . sequenceA  -- | Collapses a structure into its inner type or an effectful error collapse :: (Error e :> es, Bifurcate f) => (CErr f -> e) -> f -> Eff es (CRes f)
test/Railroad/MonadErrorSpec.hs view
@@ -5,7 +5,6 @@  import           Control.Monad.Except import           Data.Functor.Identity-import           Data.Validation import           Railroad.MonadError import           Test.Hspec @@ -27,9 +26,9 @@      describe "Predicate Operator (?>)" $ do       it "passes when predicate is met" $ do-        runMonadError (pure 10 ?> (> 5) $ const "too small") `shouldBe` Right 10+        runMonadError (pure (10 :: Int) ?> (> 5) $ const "too small") `shouldBe` Right 10       it "fails when predicate is not met" $ do-        runMonadError (pure 4 ?> (> 5) $ const "too small") `shouldBe` Left "too small"+        runMonadError (pure (4 :: Int) ?> (> 5) $ const "too small") `shouldBe` Left "too small"      describe "Recovery Operators (?~ and ??~)" $ do       it "recovers to a constant value with (?~)" $ do@@ -40,21 +39,21 @@     describe "Cardinality Operators" $ do       describe "(?+)" $ do         it "succeeds on non-empty list" $ do-          runMonadError (pure [1, 2, 3] ?+ "empty") `shouldBe` Right [1, 2, 3]+          runMonadError (pure [1, 2, 3 :: Int] ?+ "empty") `shouldBe` Right [1, 2, 3]         it "fails on empty list" $ do           runMonadError (pure ([] :: [Int]) ?+ "empty") `shouldBe` Left "empty"        describe "(?!)" $ do         let toErr = cardinalityErr "none" (const "too many")         it "extracts the single element" $ do-          runMonadError (pure [42] ?! toErr) `shouldBe` Right 42+          runMonadError (pure [42 :: Int] ?! toErr) `shouldBe` Right 42         it "fails on empty" $ do           runMonadError (pure ([] :: [Int]) ?! toErr) `shouldBe` Left "none"         it "fails on multiple elements" $ do-          runMonadError (pure [1, 2] ?! toErr) `shouldBe` Left "too many"+          runMonadError (pure [1, 2 :: Int] ?! toErr) `shouldBe` Left "too many"        describe "(?∅)" $ do         it "succeeds on empty" $ do           runMonadError (pure [] ?∅ const "not empty") `shouldBe` Right ()         it "fails on non-empty" $ do-          runMonadError (pure [1] ?∅ const "not empty") `shouldBe` Left "not empty"+          runMonadError (pure [1 :: Int] ?∅ const "not empty") `shouldBe` Left "not empty"
test/RailroadSpec.hs view
@@ -47,11 +47,11 @@       bifurcate input1 `shouldBe` Left "first"      it "List of Validation (Error Accumulation)" $ do-      let input = [Success 1, Success 2] :: [Validation String Int]-      bifurcate input `shouldBe` Right [1, 2]+      let allOk = [Success 1, Success 2] :: [Validation String Int]+      bifurcate allOk `shouldBe` Right [1, 2]         -- Note: Validation accumulates because String is a Semigroup-      let input = [Success 1, Failure "Fail A ", Failure "Fail B"] :: [Validation String Int]-      bifurcate input `shouldBe` Left "Fail A Fail B"+      let someBad = [Success 1, Failure "Fail A ", Failure "Fail B"] :: [Validation String Int]+      bifurcate someBad `shouldBe` Left "Fail A Fail B"    describe "Basic Operators (? and ??)" $ do     it "unwraps success values with (?)" $ do@@ -66,10 +66,10 @@    describe "Predicate Operator (?>)" $ do     it "passes when predicate is met" $ do-      runRail (pure 10 ?> (> 5) $ const "too small") `shouldBe` Right 10+      runRail (pure (10 :: Int) ?> (> 5) $ const "too small") `shouldBe` Right 10      it "fails when predicate is not met" $ do-      runRail (pure 4 ?> (> 5) $ const "too small") `shouldBe` Left "too small"+      runRail (pure (4 :: Int) ?> (> 5) $ const "too small") `shouldBe` Left "too small"    describe "Recovery Operators (?~ and ??~)" $ do     it "recovers to a constant value with (?~)" $ do@@ -81,21 +81,21 @@   describe "Cardinality Operators" $ do     describe "(?+)" $ do       it "succeeds on non-empty list" $ do-        runRail (pure [1, 2, 3] ?+ "empty") `shouldBe` Right [1, 2, 3]+        runRail (pure [1, 2, 3 :: Int] ?+ "empty") `shouldBe` Right [1, 2, 3]       it "fails on empty list" $ do         runRail (pure ([] :: [Int]) ?+ "empty") `shouldBe` Left "empty"      describe "(?!)" $ do       let toErr = cardinalityErr "none" (const "too many")       it "extracts the single element" $ do-        runRail (pure [42] ?! toErr) `shouldBe` Right 42+        runRail (pure [42 :: Int] ?! toErr) `shouldBe` Right 42       it "fails on empty" $ do         runRail (pure ([] :: [Int]) ?! toErr) `shouldBe` Left "none"       it "fails on multiple elements" $ do-        runRail (pure [1, 2] ?! toErr) `shouldBe` Left "too many"+        runRail (pure [1, 2 :: Int] ?! toErr) `shouldBe` Left "too many"      describe "(?∅)" $ do       it "succeeds on empty" $ do         runRail (pure [] ?∅ const "not empty") `shouldBe` Right ()       it "fails on non-empty" $ do-        runRail (pure [1] ?∅ const "not empty") `shouldBe` Left "not empty"+        runRail (pure [1 :: Int] ?∅ const "not empty") `shouldBe` Left "not empty"