Bercovici Adrian
Bercovici Adrian

Reputation: 9360

Can not print to file using IO Monad

Hello i have done my JSon type and i am trying to it to a file. I can do this from the prelude but i can't do it when using the IO Monad.I get the following error:

 Main.hs:13:24: error:
    * Couldn't match type `Char' with `[Char]'
      Expected type: String
        Actual type: Char
    * In the second argument of `writeFile', namely `val'
      In a stmt of a 'do' block: writeFile out val
      In the expression:
        do val <- renderJValue sample
           writeFile out val
   |
13 |          writeFile out val
   |                        ^^^

Main

 module Main where
        import Jlib
        import Put
        import Data.Typeable

        import System.Environment

        out="data.txt"

        main::IO()
        main=do
             val<-renderJValue sample
             writeFile out val

Why would this not work in the IO Monad since renderJValue sample in the prelude works ok .

Jlib.hs

data JValue=JString String
                |JNumber Double
                |JBool Bool
                |JNull
                |JObject [(String,JValue)]
                |JArray [JValue]
                deriving (Eq,Ord,Show)

Put.hs

sample=JArray[
                    JObject [("name",JString "adita"),("age",JNumber 13)],
                    JObject [("name",JString "dan"),("kids",JNumber 3)] ,
                    JNumber 3,
                    JBool False,
                    JString "Howdy"
                    ]

P.S renderJValue returns a string

P.S: if i start the prelude i load the module and i render the value it works:

Prelude System.Environment Put> :load Put
Ok, two modules loaded.
Prelude System.Environment Put> renderJValue sample
"[{name:adita,age:13.0},{name:dan,kids:3.0},3.0,False,Howdy]"

Upvotes: 2

Views: 124

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476997

You here use renderJValue sample as if it is an IO String:

main :: IO()
main=do
     val <- renderJValue sample
     writeFile out val

But it is in fact (given it is a function similar to this one) a function with signature renderJValue :: JValue -> String. So no IO is involved. In that case we do not use the arrow notation.

We can call the function "inline":

main :: IO()
main = do
     writeFile out (renderJValue sample)

or even shorter:

main :: IO()
main = writeFile out (renderJValue sample)

But in case the expression is rather long, this can become quite ugly. We can decide to use a let statement in that case.

You can solve this by either removing the putStrLn:

main :: IO()
main = do
    let val = renderJValue sample
    writeFile out val

Upvotes: 7

Related Questions