Skip to content

Commit

Permalink
Merge pull request #45 from purescript/either-decoding
Browse files Browse the repository at this point in the history
Either decoding for IsForeign
  • Loading branch information
garyb authored Oct 10, 2016
2 parents 930419e + a045aea commit 6dfb111
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 0 deletions.
32 changes: 32 additions & 0 deletions examples/Either.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
module Examples.Either where

import Prelude
import Control.Monad.Eff (Eff)
import Data.Either (Either)

import Data.Foreign (F, parseJSON)
import Data.Foreign.Class (class IsForeign, readEitherR, readProp)

import Control.Monad.Eff.Console (logShow, CONSOLE)

data Point = Point Number Number Number

instance showPoint :: Show Point where
show (Point x y z) = "Point " <> show [x, y, z]

instance pointIsForeign :: IsForeign Point where
read value = Point <$> readProp "x" value
<*> readProp "y" value
<*> readProp "z" value

type Response = Either (Array String) Point

main :: forall eff. Eff (console :: CONSOLE | eff) Unit
main = do
logShow do
json <- parseJSON """{ "x":1, "y": 2, "z": 3}"""
readEitherR json :: F Response

logShow do
json <- parseJSON """["Invalid parse", "Not a valid y point"]"""
readEitherR json :: F Response
13 changes: 13 additions & 0 deletions src/Data/Foreign/Class.purs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ module Data.Foreign.Class
, class AsForeign
, write
, writeProp, (.=)
, readEitherR
, readEitherL
) where

import Prelude

import Control.Alt ((<|>))
import Data.Array (range, zipWith, length)
import Data.Either (Either(..), either)
import Data.Foreign (F, Foreign, ForeignError(..), Prop(..), parseJSON, readArray, readInt, readNumber, readBoolean, readChar, readString, toForeign)
Expand Down Expand Up @@ -120,3 +123,13 @@ infixl 8 writeProp as .=

writeProp :: forall a. AsForeign a => String -> a -> Prop
writeProp k v = Prop { key: k, value: write v }

-- | Attempt to read a value that can be either one thing or another. This
-- | implementation is right biased.
readEitherR :: forall l r. (IsForeign l, IsForeign r) => Foreign -> F (Either l r)
readEitherR value = Right <$> read value <|> Left <$> read value

-- | Attempt to read a value that can be either one thing or another. This
-- | implementation is left biased.
readEitherL :: forall l r. (IsForeign l, IsForeign r) => Foreign -> F (Either l r)
readEitherL value = Left <$> read value <|> Right <$> read value

0 comments on commit 6dfb111

Please sign in to comment.