Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parsing Foreign Records fails #52

Open
Rembane opened this issue Oct 8, 2018 · 2 comments
Open

Parsing Foreign Records fails #52

Rembane opened this issue Oct 8, 2018 · 2 comments

Comments

@Rembane
Copy link

Rembane commented Oct 8, 2018

Good morning,

I have a record in a Foreign object, and when I try to turn it into a Purescript record using read' I get the following error:

Error at property "channel": Type mismatch: expected String, found Undefined

The interesting thing is that it just works if I first convert the Foreign object to a string.

Why does it behave like this?

Here's a quite large minimum failing example:

Main.js:

exports.rcrd = "{\"channel\":\"Hej där!\",\"glorp\":27,\"event\":\"mystisk uppenbarelse\",\"payload\":\"Just det...\"}";

Main.purs:

module Main where

import Prelude

import Control.Monad.Except (runExcept)
import Data.Either (Either(..))
import Data.Foldable (foldMap)
import Effect (Effect)
import Effect.Console (log, logShow)
import Foreign (Foreign, readString, renderForeignError, unsafeFromForeign)
import Simple.JSON (read', readJSON')

foreign import rcrd :: Foreign

iPrintRecords :: { channel :: String, glorp :: Int, event :: String, payload :: Foreign } -> Effect Unit
iPrintRecords r = log r.channel *> logShow r.glorp

main :: Effect Unit
main = do
  log "Hi! :D"
  log $ unsafeFromForeign rcrd
  log "----------------------------------------------------------------------------------------"
  log "This fails:"
  case runExcept (read' rcrd) of
    Left es -> log (foldMap renderForeignError es)
    Right r -> iPrintRecords r

  log "\nThis works:"
  case runExcept (readJSON' =<< readString rcrd) of
    Left es -> log (foldMap renderForeignError es)
    Right r -> iPrintRecords r
@justinwoo
Copy link
Owner

justinwoo commented Oct 8, 2018

read' works on Foreign values, but Foreign objects can be anything -- including being a String as you have defined. Your foreign import definition should actually define a JS object or your foreign import type declaration should be of type String.

@justinwoo
Copy link
Owner

If you look at the types here, you'll see how the second works, by using the JSON string:

readString :: Foreign -> F String
readJSON' :: forall a. ReadForeign a => String -> F a
bind :: forall a b m. Bind m => m a -> (a -> m b) -> m b
r1 :: F String
r1 = readString (rcrd :: Foreign)
r2 :: forall b. (String -> F b) -> F b
r2 = bind r1
r3 :: forall a. ReadJSON a => F a
r3 = r2 readJSON'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants