Question

I am trying to learn parsing JSON in Haskell via https://www.fpcomplete.com/school/pick-of-the-week/episode-1-json

When I load the file (shown after this interactive listing) I get:

> ghci
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> :set -v
hiding package binary-0.5.1.1 to avoid conflict with later version binary-0.7.1.0
hiding package Cabal-1.16.0 to avoid conflict with later version Cabal-1.18.0
hiding package QuickCheck-2.4.2 to avoid conflict with later version QuickCheck-2.6
hiding package syb-0.3.7 to avoid conflict with later version syb-0.4.0
hiding package hakyll-4.2.2.0 to avoid conflict with later version hakyll-4.3.1.0
wired-in package ghc-prim mapped to ghc-prim-0.3.0.0-d5221a8c8a269b66ab9a07bdc23317dd
wired-in package integer-gmp mapped to integer-gmp-0.5.0.0-2f15426f5b53fe4c6490832f9b20d8d7
wired-in package base mapped to base-4.6.0.1-6c351d70a24d3e96f315cba68f3acf57
wired-in package rts mapped to builtin_rts
wired-in package template-haskell mapped to template-haskell-2.8.0.0-c2c1b21dbbb37ace4b7dc26c966ec664
wired-in package dph-seq not found.
wired-in package dph-par not found.
Prelude> :l X03ObjSetsTweetReader
*** Chasing dependencies:
Chasing modules from: 
Stable obj: []
Stable BCO: []
unload: retaining objs []
unload: retaining bcos []
Ready for upsweep []
Upsweep completely successful.
*** Deleting temp files:
Deleting: 
*** Chasing dependencies:
Chasing modules from: *X03ObjSetsTweetReader.hs
Stable obj: []
Stable BCO: []
unload: retaining objs []
unload: retaining bcos []
Ready for upsweep
  [NONREC
      ModSummary {
         ms_hs_date = 2013-10-02 02:30:39 UTC
         ms_mod = main:X03ObjSetsTweetSetTest,
         ms_textual_imps = [import (implicit) Prelude, import Control.Monad,
                            import Control.Applicative, import Data.Monoid, import Data.Aeson,
                            import Parser (),
                            import qualified Data.ByteString.Lazy.Char8 as C8,
                            import qualified Data.ByteString.Lazy as BL]
         ms_srcimps = []
      }]
*** Deleting temp files:
Deleting: 
compile: input file X03ObjSetsTweetReader.hs
Created temporary directory: /var/folders/dw/c7gq7tw9339grqjctgwbmgzm0000gy/T/ghc18739_0
*** Checking old interface for main:X03ObjSetsTweetSetTest:
[1 of 1] Compiling X03ObjSetsTweetSetTest ( X03ObjSetsTweetReader.hs, interpreted )
*** Parser:
*** Renamer/typechecker:
*** Desugar:
Result size of Desugar (after optimization)
  = {terms: 974, types: 767, coercions: 0}
*** Simplifier:
Result size of Simplifier iteration=1
  = {terms: 966, types: 761, coercions: 45}
Result size of Simplifier = {terms: 966, types: 761, coercions: 45}
*** Tidy Core:
Result size of Tidy Core = {terms: 966, types: 761, coercions: 45}
*** CorePrep:
Result size of CorePrep
  = {terms: 1,646, types: 1,390, coercions: 45}
*** ByteCodeGen:
Upsweep completely successful.
*** Deleting temp files:
Deleting: /var/folders/dw/c7gq7tw9339grqjctgwbmgzm0000gy/T/ghc18739_0/ghc18739_0.c /var/folders/dw/c7gq7tw9339grqjctgwbmgzm0000gy/T/ghc18739_0/ghc18739_0.o
Warning: deleting non-existent /var/folders/dw/c7gq7tw9339grqjctgwbmgzm0000gy/T/ghc18739_0/ghc18739_0.c
Warning: deleting non-existent /var/folders/dw/c7gq7tw9339grqjctgwbmgzm0000gy/T/ghc18739_0/ghc18739_0.o
Ok, modules loaded: X03ObjSetsTweetSetTest.
*X03ObjSetsTweetSetTest> main
*** Parser:
*** Desugar:
*** Simplify:
*** CorePrep:
*** ByteCodeGen:
Loading package array-0.4.0.1 ... linking ... done.
Loading package deepseq-1.3.0.1 ... linking ... done.
Loading package primitive-0.5.0.1 ... linking ... done.
Loading package vector-0.10.0.1 ... linking ... done.
Loading package bytestring-0.10.0.2 ... linking ... done.
Loading package text-0.11.3.1 ... linking ... done.
Loading package hashable-1.1.2.5 ... linking ... done.
Loading package unordered-containers-0.2.3.0 ... linking ... done.
Loading package transformers-0.3.0.0 ... linking ... done.
Loading package mtl-2.1.2 ... linking ... done.
Loading package parsec-3.1.3 ... linking ... done.
Loading package containers-0.5.0.0 ... linking ... done.
Loading package attoparsec-0.10.4.0 ... linking ... done.
Loading package pretty-1.1.1.0 ... linking ... done.
Loading package old-locale-1.0.0.5 ... linking ... done.
Loading package time-1.4.0.1 ... linking ... done.
Loading package HUnit-1.2.5.2 ... linking ... done.
Loading package random-1.0.1.1 ... linking ... done.
Loading package template-haskell ... linking ... done.
Loading package QuickCheck-2.6 ... linking ... done.
Loading package type-equality-0.1.2 ... linking ... done.
Loading package RepLib-0.5.3.1 ... linking ... done.
Loading package bimap-0.2.4 ... linking ... done.
Loading package filepath-1.3.0.1 ... linking ... done.
*** gcc:
'/usr/bin/gcc' '-m64' '-fno-stack-protector' '-m64' '-L/Library/Frameworks/GHC.framework/Versions/7.6.3-x86_64/usr/lib/ghc-7.6.3/unix-2.6.0.1' '--print-file-name' 'libdl.dylib'
Loading package unix-2.6.0.1 ... linking ... done.
Loading package directory-1.2.0.1 ... linking ... done.
Loading package unbound-0.4.2 ... linking ... done.
Loading package pi-forall-0.1 ... linking ... <interactive>: 
lookupSymbol failed in relocateSection (relocate external)
/Users/carr/Library/Haskell/ghc-7.6.3/lib/pi-forall-0.1/lib/HSpi-forall-0.1.o: unknown symbol `_pizmforallzm0zi1_LayoutToken_makeTokenParser_info'
ghc: unable to load package `pi-forall-0.1'
*X03ObjSetsTweetSetTest> 

Why in the heck would it be loading pi-forall ?? That is Stephanie Weirich's demo impl from OPLSS 2013. How can I track down who/what/why this is being loaded?

Here is X03ObjSetsTweetSetTest.hs:

module X03ObjSetsTweetSetTest where

import qualified Data.ByteString.Lazy       as BL
import qualified Data.ByteString.Lazy.Char8 as C8
import           Parser()
import           Data.Aeson
import           Data.Monoid
import           Control.Applicative
import           Control.Monad

data Recipe = Recipe
  { recipeName :: String
  , ingredients :: [Ingredient]
  , steps :: [Step]
  } deriving Show

type Measure = String

data Ingredient = Ingredient 
  { ingredientName :: String
  , quantity :: Int
  , measure :: Maybe Measure
  } deriving Show

data Step = Step
  { stepName :: String
  , order :: Int
  , stepDuration :: Maybe Duration
  } deriving (Eq, Show)

instance Ord Step where
    compare s1 s2 = compare (order s1) (order s2)

data Duration = Duration
  { duration :: Int
  , durationMeasure :: Measure
  } deriving (Eq, Show)

-------------------------------------------------------------------------------

instance FromJSON Recipe where
    parseJSON (Object r) = Recipe <$>
                           r .: "name" <*>
                           r .: "ingredients" <*>
                           r .: "steps"
    parseJSON _ = mzero

instance ToJSON Recipe where
    toJSON (Recipe n i s) = object ["name" .= n, "ingredients" .= i, "steps" .= s]

-------------------------------------------------------------------------------

instance FromJSON Step where
    parseJSON (Object s) = Step <$>
                           s .: "step" <*>
                           s .: "order" <*>
                           s .:? "duration"
    parseJSON _ = mzero

instance ToJSON Step where
    toJSON (Step s o d) = object ["step" .= s, "order" .= o, "duration" .= d]

-------------------------------------------------------------------------------

instance FromJSON Ingredient where
    parseJSON (Object i) = Ingredient <$>
                           i .: "name" <*>
                           i .: "quantity" <*>
                           i .:? "measure" 
    parseJSON _ = mzero

instance ToJSON Ingredient where
    toJSON (Ingredient n q m) = object ["name" .= n, "quantity" .= q, "measure" .= m]

-------------------------------------------------------------------------------
instance FromJSON Duration where
    parseJSON (Object d) = Duration <$>
                           d .: "duration" <*>
                           d .: "measure"
    parseJSON _ = mzero

instance ToJSON Duration where
    toJSON (Duration d m) = object ["duration" .= d, "measure" .= m]

-------------------------------------------------------------------------------

main :: IO ()
main = do
    let toParse = C8.unlines $ map C8.pack [
                                    "{ ",
                                    "    \"name\": \"Ciambellone Cake\", ",
                                    "    \"ingredients\": [ ",
                                    "        { ",
                                    "            \"name\": \"Flour\", ",
                                    "            \"quantity\": 250, ",
                                    "            \"measure\": \"gr\" ",
                                    "        }, ",
                                    "        { ",
                                    "            \"name\": \"Sugar\", ",
                                    "            \"quantity\": 250, ",
                                    "            \"measure\": \"gr\" ",
                                    "        }, ",
                                    "        { ",
                                    "            \"name\": \"Sunflower Oil\", ",
                                    "            \"quantity\": 130, ",
                                    "            \"measure\": \"ml\" ",
                                    "        }, ",
                                    "        { ",
                                    "            \"name\": \"Water\", ",
                                    "            \"quantity\": 130, ",
                                    "            \"measure\": \"ml\" ",
                                    "        }, ",
                                    "        { ",
                                    "            \"name\": \"Egg\", ",
                                    "            \"quantity\": 3 ",
                                    "        }, ",
                                    "        { ",
                                    "            \"name\": \"Yeast\", ",
                                    "            \"quantity\": 1 ",
                                    "        } ",
                                    "    ], ",
                                    "    \"steps\": [ ",
                                    "        { ",
                                    "            \"step\": \"Mix everything\", ",
                                    "            \"order\": 1 ",
                                    "        }, ",
                                    "        { ",
                                    "            \"step\": \"Cook in oven at 200 degrees\", ",
                                    "            \"order\": 2, ",
                                    "            \"duration\": { ",
                                    "                \"duration\": 30, ",
                                    "                \"measure\": \"minutes\" ",
                                    "            } ",
                                    "        } ",
                                    "    ] ",
                                    "} "
                                ]
      in case (eitherDecode' toParse :: Either String Recipe) of
        Right r -> print r
        Left e -> C8.putStrLn $ C8.pack e <> " in " <> toParse
Was it helpful?

Solution

See Gabriel's response - cut-n-paste error.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top