@@ -41,13 +41,14 @@ import Data.Array.NonEmpty (NonEmptyArray, fromArray, toArray)
4141import Data.Bifunctor (lmap)
4242import Data.BigInt (BigInt)
4343import Data.BigInt as BigInt
44−import Data.DateTime (DateTime(..))
45−import Data.DateTime as DateTime
46−import Data.Either (Either(..), either, hush, note)
44+import Data.DateTime (DateTime)
45+import Data.Either (Either(..), hush, note)
46+import Data.Foldable (class Foldable, foldl)
4747import Data.FoldableWithIndex (foldrWithIndex)
48+import Data.FunctorWithIndex (mapWithIndex)
4849import Data.Identity (Identity(..))
4950import Data.Int as Int
50−import Data.JSDate (JSDate, toISOString)
51+import Data.JSDate (JSDate)
5152import Data.JSDate as JSDate
5253import Data.List.NonEmpty (NonEmptyList, singleton)
5354import Data.Map (Map)
@@ -57,8 +58,7 @@ import Data.Newtype (class Newtype)
5758import Data.Nullable (Nullable, toMaybe, toNullable)
5859import Data.Number as Number
5960import Data.Symbol (class IsSymbol, reflectSymbol)
60−import Data.Traversable (sequence, traverse)
61−import Data.TraversableWithIndex (traverseWithIndex)
61+import Data.Traversable (traverse)
6262import Data.Tuple (Tuple(..))
6363import Data.Variant (Variant, inj, on)
6464import Effect.Exception (message, try)
@@ -216,7 +216,7 @@ instance ReadForeign Boolean where
216216 readImpl = readBoolean
217217
218218instance ReadForeign a ⇒ ReadForeign (Array a) where
219− readImpl = traverseWithIndex readAtIdx <=< readArray
219+ readImpl = sequenceCombining <<< mapWithIndex readAtIdx <=< readArray
220220
221221instance ReadForeign a ⇒ ReadForeign (Maybe a) where
222222 readImpl = readNullOrUndefined readImpl
@@ -242,8 +242,21 @@ instance (ReadForeign a, ReadForeign b) ⇒ ReadForeign (Either a b) where
242242 _ -> except $ Left (pure $ ForeignError $ "Invalid Either tag " <> tpe)
243243
244244instance ReadForeign a ⇒ ReadForeign (Object.Object a) where
245− readImpl = sequence <<< Object.mapWithKey readProp <=< readObject'
245+ readImpl = gatherErrors <<< Object.mapWithKey readProp <=< readObject'
246246 where
247+ gatherErrors :: Object (F a) -> F (Object a)
248+ gatherErrors = Object.toUnfoldable
249+ >>> Array.foldl fn (Right (Object.empty))
250+ >>> except
251+ where
252+ fn :: _ -> _ -> (Either MultipleErrors (Object a))
253+ fn acc (Tuple k v) = do
254+ case acc, runExcept v of
255+ Left errs, Left errsNew -> Left (errs <> errsNew)
256+ Left errs, Right _ -> Left errs
257+ Right obj, Right value -> Right (Object.insert k value obj)
258+ Right _, Left errs -> Left errs
259+
247260 readProp key value = except $ lmap (map (ErrorAtProperty key))
248261 (readImpl value # runExcept)
249262
@@ -321,16 +334,20 @@ instance
321334 , Row.Cons name ty from' to
322335 ) ⇒
323336 ReadForeignFields (Cons name ty tail) from to where
324− getFields _ obj = do
325− compose <$> first <*> rest
337+ getFields _ obj = except
338+ case runExcept first, runExcept rest of
339+ Right f, Right r -> Right (f <<< r)
340+ Left e1, Left e2 -> Left (e1 <> e2)
341+ Right _, Left es -> Left es
342+ Left es, Right _ -> Left es
326343 where
327− value = withExcept' (readImpl =<< readProp name obj)
344+ value = enrichErrorWithPropName (readImpl =<< readProp name obj)
328345 first = Builder.insert nameP <$> value
329346 rest = getFields tailP obj
330347 nameP = Proxy ∷ Proxy name
331348 tailP = Proxy ∷ Proxy tail
332349 name = reflectSymbol nameP
333− withExcept' = (withExcept <<< map) (ErrorAtProperty name)
350+ enrichErrorWithPropName = (withExcept <<< map) (ErrorAtProperty name)
334351
335352readAtIdx ∷ ∀ a. ReadForeign a ⇒ Int → Foreign → F a
336353readAtIdx i f = withExcept (map (ErrorAtIndex i)) (readImpl f)
@@ -552,3 +569,18 @@ instance ReadForeign DateTime where
552569unsafeStringToInt :: String → Int
553570unsafeStringToInt = Int.fromString >>>
554571 (fromMaybe' \_ -> unsafeCrashWith "impossible")
572+
573+sequenceCombining :: forall f a.
574+ Monoid (f a) =>
575+ Foldable f =>
576+ Applicative f =>
577+ f (F a) -> F (f a)
578+sequenceCombining = foldl fn (Right mempty) >>> except
579+ where
580+ fn :: _ -> _ -> (Either MultipleErrors (f a))
581+ fn acc elem = do
582+ case acc, runExcept elem of
583+ Left errs, Left errsNew -> Left (errs <> errsNew)
584+ Left errs, Right _ -> Left errs
585+ Right values, Right value -> Right (values <> pure value)
586+ Right _, Left errs -> Left errs