Having trouble generating arbitrary json with Haskell's Aeson package - haskell

I'm a Haskell newb, having only just finished reading LYAH. I am reading this Aeson tutorial, but I'm having trouble executing most of the code examples. For instance, I have the following in Scratch01.hs ...
{-# LANGUAGE OverloadedStrings #-}
module Scratch01 where
import Data.Aeson
import GHC.Exts
val :: Value
val = Object $ fromList [
("numbers", Array $ fromList [Number 1, Number 2, Number 3]),
("boolean", Bool True) ]
... and I'm trying to execute it like this
$ ghci --version
The Glorious Glasgow Haskell Compilation System, version 7.8.3
$ ghci -XOverloadedStrings
GHCi, version 7.8.3: http://www.haskell.org/ghc/ :? for help
Prelude> :load Scratch01.hs
[1 of 1] Compiling Scratch01 ( Scratch01.hs, interpreted )
Scratch01.hs:10:3:
Couldn't match expected type ‘Item Object’
with actual type ‘(t0, Value)’
The type variable ‘t0’ is ambiguous
In the expression:
("numbers", Array $ fromList [Number 1, Number 2, Number 3])
In the first argument of ‘fromList’, namely
‘[("numbers", Array $ fromList [Number 1, Number 2, ....]),
("boolean", Bool True)]’
In the second argument of ‘($)’, namely
‘fromList
[("numbers", Array $ fromList [Number 1, Number 2, ....]),
("boolean", Bool True)]’
Scratch01.hs:10:33:
Couldn't match expected type ‘Item Array’ with actual type ‘Value’
In the expression: Number 1
In the first argument of ‘fromList’, namely
‘[Number 1, Number 2, Number 3]’
Failed, modules loaded: none.
Prelude>
I've been tinkering with the types for a bit, but I'm stumped. Am I using the wrong version of GHC or something?
Edit
I did what artyom suggested. This works:
{-# LANGUAGE OverloadedStrings #-}
module Scratch01 where
import Data.Aeson
import qualified Data.HashMap.Lazy as HM
import qualified Data.Vector as V
val :: Value
val = Object $ HM.fromList [
("numbers", Array $ V.fromList [Number 1, Number 2, Number 3]),
("boolean", Bool True) ]

Related

RIO.ByteString.split not working as documented

Trying an example from split docs:
$ stack ghci
...
Prelude> :set -XOverloadedStrings
Prelude> import qualified RIO.ByteString as B
Prelude B> B.split 'a' "aXaXaXa"
<interactive>:3:9: error:
• Couldn't match expected type ‘GHC.Word.Word8’
with actual type ‘Char’
• In the first argument of ‘B.split’, namely ‘'a'’
In the expression: B.split 'a' "aXaXaXa"
In an equation for ‘it’: it = B.split 'a' "aXaXaXa"
What am I missing?
The documentation is taken from the split :: Char -> ByteString -> [ByteString] function of the Data.ByteString.Char8 module. This uses the code points 0-255 as Char for the corresponding byte.
You can however use the byte value instead. For example 'a' has as byte value 97, so we can split this with:
Prelude> :set -XOverloadedStrings
Prelude> import qualified RIO.ByteString as B
Prelude B> B.split 97 "aXaXaXa"
["","X","X","X",""]

Couldn't match type ‘[Char]’ with ‘Data.Text.Internal.Text’

I am trying to figure out, how to build JSON in Haskell with the following example:
module Main where
import GHC.Exts
import Data.Aeson
import qualified Data.Text.Lazy.IO as T
import qualified Data.Text.Lazy.Encoding as T
val :: Value
val = Object $ fromList [
("numbers", Array $ fromList [Number 1, Number 2, Number 3]),
("boolean", Bool True) ]
main :: IO ()
main = T.putStrLn . T.decodeUtf8 . encode $ val
When I tried to compile, the compiler complains:
• Couldn't match type ‘[Char]’ with ‘Data.Text.Internal.Text’
Expected type: Item Object
Actual type: ([Char], Value)
• In the expression: ("boolean", Bool True)
In the first argument of ‘fromList’, namely
‘[("numbers", Array $ fromList [Number 1, Number 2, ....]),
("boolean", Bool True)]’
In the second argument of ‘($)’, namely
‘fromList
[("numbers", Array $ fromList [Number 1, Number 2, ....]),
("boolean", Bool True)]’
|
12 | ("boolean", Bool True) ]
| ^^^^^^^^^^^^^^^^^^^^^^
You need to put OverloadedStrings extension on top of the file:
#!/usr/bin/env stack
-- stack script --resolver lts-12.7
{-# LANGUAGE OverloadedStrings #-}
import Data.Aeson
import qualified Data.Text.Lazy.Encoding as T
import qualified Data.Text.Lazy.IO as T
import GHC.Exts
val :: Value
val =
Object $
fromList
[ ("numbers", Array $ fromList [Number 1, Number 2, Number 3])
, ("boolean", Bool True)
]
main :: IO ()
main = T.putStrLn . T.decodeUtf8 . encode $ val
And on executing them:
$ stack fuse.hs
{"boolean":true,"numbers":[1,2,3]}
To understand the reasons on why that makes it work, refer to this answer.
The error you get is about wrong string representation. Haskell has many of them, e.g. ByteString (strict or lazy), Text (strict or lazy), String (alias for [Char]). The last one is the default and also the one you should avoid most of the time.
Aeson library uses the Text as string representation. You can fix your code using T.pack before the string (to convert it to Text), like this:
val :: Value
val =
Object $
fromList
[ (T.pack "numbers", Array $ fromList [Number 1, Number 2, Number 3])
, (T.pack "boolean", Bool True)
]
Or you can just enable OverloadedStrings extension. When it's on then Haskell compiler will try to figure out which string representation it should use. Just put {-# LANGUAGE OverloadedStrings #-} at the top of your file and it should work.

Hspec unable to load interface for Spec file

I am trying to run hspec but getting error as "Failed to load interface for Spec file". I tried similar example from github, got same error. Please suggest where I am going wrong...(PS: I am able to run this with stack).
Example from github (https://github.com/FranklinChen/twenty-four-days2015-of-hackage)
I have following files:
-- src.HintExample.hs
module HintExample where
import SortWrapper (Sort)
import qualified Language.Haskell.Interpreter as I
import Language.Haskell.Interpreter (OptionVal((:=)))
-- | Dynamically load a 'Sort' implementation from a file.
-- src is needed to pick up our SortWrapper.
-- sort-plugins is a sample user plugins directory
loadSort :: I.MonadInterpreter m =>
String -- ^ module name
-> String -- ^ function name
-> m Sort
loadSort moduleName functionName = do
I.set [I.searchPath := ["src", "sort-plugins"]]
I.loadModules [moduleName]
I.setImports [moduleName, "SortWrapper"]
I.interpret (moduleName ++ "." ++ functionName) (I.as :: Sort)
And test file as
-- test.HintExampleSpec.hs
module HintExampleSpec where
import SortWrapper (Sort(Sort))
import HintExample (loadSort)
import qualified Language.Haskell.Interpreter as I
import Test.Hspec (Spec, hspec, describe, it, shouldBe)
import Test.Hspec.QuickCheck (prop)
-- | Required for auto-discovery.
spec :: Spec
spec =
describe "hint" $ do
it "dynamically loads a correct polymorphic sort function" $ do
Right (Sort ourSort) <-
I.runInterpreter (loadSort "OurSorter" "ourSort")
ourSort "ebcad" `shouldBe` "abcde"
ourSort [1 :: Int, 5, 4, 3, 7] `shouldBe` [1, 3, 4, 5, 7]
it "dynamically loads a wrong (only head) sort function" $ do
Right (Sort onlyHead) <-
I.runInterpreter (loadSort "OurSorter" "onlyHead")
onlyHead "ebcad" `shouldBe` "e"
onlyHead [True, False] `shouldBe` [True]
main :: IO ()
main = hspec spec
Spec file (Spec.hs) in test directory as:
{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
running as:
runhaskell test/Spec.hs

Top-level expression evaluation at compile time

Is there any way to ensure, that an expression like the following would be evaluated at compile time?
myList :: [Int]
myList = sort [3,2,0,1]
If what you're evaluating is an instance of Lift, you can evaluate it at compile time using TemplateHaskell:
{-# LANGUAGE TemplateHaskell #-}
module Sort where
import Data.List
import Language.Haskell.TH.Syntax
myList :: [Int]
myList = $(lift (sort [3,2,0,1] :: [Int]))
If you want, you can check what it has compiled to with -ddump-splices:
$ ghc -ddump-splices sort
[1 of 1] Compiling Sort ( sort.hs, sort.o )
sort.hs:9:12-41: Splicing expression
lift (sort [3, 2, 0, 1] :: [Int]) ======> [0, 1, 2, 3]

Is it possible to import a library with name-solving priority?

Mind the following file:
import Common
main = print (length [1,2,3])
Common is a library that reorganizes functions from Prelude in order to export my favored versions (i.e., fold-based functions instead of list-based functions). This is giving name conflicts:
test.hs:3:15:
Ambiguous occurrence ‘length’
It could refer to either ‘Prelude.length’,
imported from ‘Prelude’ at test.hs:1:1
(and originally defined in ‘GHC.List’)
or ‘Common.length’, imported from ‘Common’ at test.hs:1:1-11
Since the idea is avoiding bureaucracy when creating new files, just using Import Prelude hiding ... wouldn't help here. Is there any way to tell GHC to favor Common.hs's definitions over Prelude's?
There's no way to give priority, but one can easily override individual names. For example, to override length:
module Common where
import Prelude hiding (length)
import qualified Data.List
length :: Num n => [a] -> n
length = Data.List.genericLength
You can check that things are going well in ghci:
% ghci -XNoImplicitPrelude test.hs
GHCi, version 7.10.1: http://www.haskell.org/ghc/ :? for help
[1 of 1] Compiling Common ( test.hs, interpreted )
Ok, modules loaded: Common.
*Common> :t length
length :: Num n => [a] -> n
*Common> :t (+)
(+) :: Num a => a -> a -> a

Resources