
Hello, in my program i have a function which can be simplified like this: writeProgramInfo :: Handle -> ProgramInfo -> IO () writeProgramInfo handle program = do hPrintf handle "hello" This is using the hPrintf from Text.Printf. Unfortunately that hPrintf works on String parameters which is not good enough because I need unicode character support (if I use unpack it works on linux but complains about invalid characters on windows, I guess because my locale on linux is utf-8 but on windows it's a local codepage). So I found the Text.Format library: http://hackage.haskell.org/packages/archive/text-format/0.3.0.7/doc/html/Dat... Which appears to solve exactly that problem (out of the box Text support). However I can't just install the library, add the import statements, and replace hPrintf by TF.hprint and change the format string, that doesn't work; if I change this function to: import qualified Data.Text.Format as TF writeProgramInfo :: Handle -> ProgramInfo -> IO () writeProgramInfo handle program = do TF.hprint handle "hello" I get this error message at build time: Couldn't match expected type `IO ()' with actual type `ps0 -> m0 ()' In the return type of a call of `TF.hprint' In the expression: TF.hprint handle "hello" In the expression: do { TF.hprint handle "hello" } Now this clearly results from the type of hprint, which is: hprint :: (MonadIOhttp://hackage.haskell.org/packages/archive/transformers/0.2.2.0/doc/html/Co...m, Paramshttp://hackage.haskell.org/packages/archive/text-format/0.3.0.7/doc/html/Dat...ps) => Handlehttp://hackage.haskell.org/packages/archive/base/4.4.1.0/doc/html/GHC-IO-Han...-> Formathttp://hackage.haskell.org/packages/archive/text-format/0.3.0.7/doc/html/Dat...-> ps -> m ()http://hackage.haskell.org/packages/archive/ghc-prim/0.2.0.0/doc/html/GHC-Un... while the type of hPrintf is: hPrintfhttp://hackage.haskell.org/packages/archive/base/4.2.0.1/doc/html/Text-Print...:: HPrintfTypehttp://hackage.haskell.org/packages/archive/base/4.2.0.1/doc/html/Text-Print...r => Handlehttp://hackage.haskell.org/packages/archive/base/4.2.0.1/doc/html/GHC-IO-Han...-> Stringhttp://hackage.haskell.org/packages/archive/base/4.2.0.1/doc/html/Data-Char....-> r with the precision: The return type is restricted to (IOhttp://hackage.haskell.org/packages/archive/base/4.2.0.1/doc/html/System-IO....a) . Well I didn't completely 'get' the monad thing yet. I think I'm pretty close.. but not there yet. I'm pretty sure understanding this specific example will take me one step closer... What am I missing here? Thank you! Emmanuel

and the subject of the mail is because if actually give parameters to the
print call I get a different error message, which is the first one I saw:
No instance for (MonadIO ((->) t0))
arising from a use of `TF.hprint'
Possible fix: add an instance declaration for (MonadIO ((->) t0))
but here I might be misusing the library in yet another way. I would first
focus on the "no parameters" case.
Emmanuel
On Sat, Oct 20, 2012 at 8:24 PM, Emmanuel Touzery
Hello,
in my program i have a function which can be simplified like this:
writeProgramInfo :: Handle -> ProgramInfo -> IO () writeProgramInfo handle program = do hPrintf handle "hello"
This is using the hPrintf from Text.Printf.
Unfortunately that hPrintf works on String parameters which is not good enough because I need unicode character support (if I use unpack it works on linux but complains about invalid characters on windows, I guess because my locale on linux is utf-8 but on windows it's a local codepage). So I found the Text.Format library:
http://hackage.haskell.org/packages/archive/text-format/0.3.0.7/doc/html/Dat...
Which appears to solve exactly that problem (out of the box Text support). However I can't just install the library, add the import statements, and replace hPrintf by TF.hprint and change the format string, that doesn't work; if I change this function to:
import qualified Data.Text.Format as TF
writeProgramInfo :: Handle -> ProgramInfo -> IO () writeProgramInfo handle program = do TF.hprint handle "hello"
I get this error message at build time:
Couldn't match expected type `IO ()' with actual type `ps0 -> m0 ()' In the return type of a call of `TF.hprint' In the expression: TF.hprint handle "hello" In the expression: do { TF.hprint handle "hello" }
Now this clearly results from the type of hprint, which is: hprint :: (MonadIOhttp://hackage.haskell.org/packages/archive/transformers/0.2.2.0/doc/html/Co...m, Paramshttp://hackage.haskell.org/packages/archive/text-format/0.3.0.7/doc/html/Dat...ps) => Handlehttp://hackage.haskell.org/packages/archive/base/4.4.1.0/doc/html/GHC-IO-Han...-> Formathttp://hackage.haskell.org/packages/archive/text-format/0.3.0.7/doc/html/Dat...-> ps -> m ()http://hackage.haskell.org/packages/archive/ghc-prim/0.2.0.0/doc/html/GHC-Un...
while the type of hPrintf is: hPrintfhttp://hackage.haskell.org/packages/archive/base/4.2.0.1/doc/html/Text-Print...:: HPrintfTypehttp://hackage.haskell.org/packages/archive/base/4.2.0.1/doc/html/Text-Print...r => Handlehttp://hackage.haskell.org/packages/archive/base/4.2.0.1/doc/html/GHC-IO-Han...-> Stringhttp://hackage.haskell.org/packages/archive/base/4.2.0.1/doc/html/Data-Char....-> r
with the precision: The return type is restricted to (IOhttp://hackage.haskell.org/packages/archive/base/4.2.0.1/doc/html/System-IO....a) .
Well I didn't completely 'get' the monad thing yet. I think I'm pretty close.. but not there yet. I'm pretty sure understanding this specific example will take me one step closer... What am I missing here?
Thank you!
Emmanuel

Hi Emmanuel,
writeProgramInfo :: Handle -> ProgramInfo -> IO () writeProgramInfo handle program = do TF.hprint handle "hello"
I get this error message at build time:
Couldn't match expected type `IO ()' with actual type `ps0 -> m0 ()' In the return type of a call of `TF.hprint' In the expression: TF.hprint handle "hello" In the expression: do { TF.hprint handle "hello" }
GHC expects an expression of 'IO ()' - the return type of writeProgramInfo - but the expression 'TF.hprint handle "hello"' has the type 'ps0 -> m0 ()' Look at the type of 'hprint': hprint :: (MonadIO m, Params ps) => Handle -> Format -> ps -> m () Your call of 'hprint' is missing the last argument, the 'ps'. So instead of 'm ()' you're returing the function 'ps -> m()', that's what GHC tries to tell you. You might be confused, because 'hprintf' uses some magic to allow multiple parameters and can even be called without any parameter. 'hprint' uses are more explict - and imho a nicer and simpler approach - for the parameters, but the parameter can't be completly omitted, it has to be at least '()'. So in your case: TF.hprint handle "hello" () Greetings, Daniel

Thank you! And yes that works...
But what if i do want to give several parameters to hprint? In my second
email i noted i get a different error message in that case?
so for instance:
TF.hprint handle " {} {}" "a" "b"
In that case I get that "no instance for.." error message.
No instance for (MonadIO ((->) t0))
arising from a use of `TF.hprint'
Possible fix: add an instance declaration for (MonadIO ((->) t0))
In the expression: TF.hprint handle " {} {}" "a" "b"
In the expression: do { TF.hprint handle " {} {}" "a" "b" }
In an equation for `writeProgramInfo':
writeProgramInfo handle program
= do { TF.hprint handle " {} {}" "a" "b" }
On 20 Oct 2012 21:48, "Daniel Trstenjak"
Hi Emmanuel,
writeProgramInfo :: Handle -> ProgramInfo -> IO () writeProgramInfo handle program = do TF.hprint handle "hello"
I get this error message at build time:
Couldn't match expected type `IO ()' with actual type `ps0 -> m0 ()' In the return type of a call of `TF.hprint' In the expression: TF.hprint handle "hello" In the expression: do { TF.hprint handle "hello" }
GHC expects an expression of 'IO ()' - the return type of writeProgramInfo - but the expression 'TF.hprint handle "hello"' has the type 'ps0 -> m0 ()'
Look at the type of 'hprint': hprint :: (MonadIO m, Params ps) => Handle -> Format -> ps -> m ()
Your call of 'hprint' is missing the last argument, the 'ps'. So instead of 'm ()' you're returing the function 'ps -> m()', that's what GHC tries to tell you.
You might be confused, because 'hprintf' uses some magic to allow multiple parameters and can even be called without any parameter.
'hprint' uses are more explict - and imho a nicer and simpler approach - for the parameters, but the parameter can't be completly omitted, it has to be at least '()'.
So in your case: TF.hprint handle "hello" ()
Greetings, Daniel
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

On Sat, Oct 20, 2012 at 09:53:09PM +0200, Emmanuel Touzery wrote:
Thank you! And yes that works...
But what if i do want to give several parameters to hprint? In my second email i noted i get a different error message in that case? so for instance: TF.hprint handle " {} {}" "a" "b"
Look at the instances of the type class Params: http://hackage.haskell.org/packages/archive/text-format/0.3.0.8/doc/html/Dat... It tells us, that for multiple parameters you can use a list '["a", "b"]' or a tuple with up to ten elements '("a", "b")'. Greetings, Daniel

Thank you, you're right again. I had actually tried that but it failed and I didn't look at the compilation error hard enough. It said: Ambiguous type variable `t0' in the constraints: (Data.Text.Buildable.Buildable t0) arising from a use of `TF.hprint' at JsonWriter.hs:94:17-25 (Data.String.IsString t0) arising from the literal `"b"' at JsonWriter.hs:94:49-51 And now that thanks to your email I knew this was the right direction, I read properly the error message and got to that working solution: TF.hprint handle " {} {}" ["a" :: T.Text, "b" :: T.Text] Unfortunately it's not very compact. I guess the problem is that this Buildable data can take either a String or a Text and because I build with OverloadedStrings the compiler doesn't know which one to prioritize? If that's the case I wish Buildable would only accept Text and if you really want to give a String you could always pack it. But maybe I'm missing something. Is there no way to get a more compact line in this case? Although most of the time it's true that the parameters for the print will in fact be other values which were assigned and which type was determined previously in the program. Anyway thank you a lot, you unblocked me! Emmanuel On Sat, Oct 20, 2012 at 10:02 PM, Daniel Trstenjak < daniel.trstenjak@gmail.com> wrote:
On Sat, Oct 20, 2012 at 09:53:09PM +0200, Emmanuel Touzery wrote:
Thank you! And yes that works...
But what if i do want to give several parameters to hprint? In my second email i noted i get a different error message in that case? so for instance: TF.hprint handle " {} {}" "a" "b"
Look at the instances of the type class Params:
http://hackage.haskell.org/packages/archive/text-format/0.3.0.8/doc/html/Dat...
It tells us, that for multiple parameters you can use a list '["a", "b"]' or a tuple with up to ten elements '("a", "b")'.
Greetings, Daniel
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners

On Sat, Oct 20, 2012 at 10:12:39PM +0200, Emmanuel Touzery wrote:
Thank you, you're right again. I had actually tried that but it failed and I didn't look at the compilation error hard enough.
It said: Ambiguous type variable `t0' in the constraints: (Data.Text.Buildable.Buildable t0) arising from a use of `TF.hprint' at JsonWriter.hs:94:17-25 (Data.String.IsString t0) arising from the literal `"b"' at JsonWriter.hs:94:49-51
And now that thanks to your email I knew this was the right direction, I read properly the error message and got to that working solution:
TF.hprint handle " {} {}" ["a" :: T.Text, "b" :: T.Text]
Unfortunately it's not very compact. I guess the problem is that this Buildable data can take either a String or a Text and because I build with OverloadedStrings the compiler doesn't know which one to prioritize?
The issue arises, because Text and a type of the Json library you're using, both have an instance for the type class IsString, which is the base for the OverloadedStrings extension. I don't now if there's a "nicer" way to tell GHC which one it should use. Instead of giving each element a type you could give the whole list a type: ["a", "b"] :: [T.Text] Greetings, Daniel

On Sat, Oct 20, 2012 at 10:34:27PM +0200, Daniel Trstenjak wrote:
The issue arises, because Text and a type of the Json library you're using, both have an instance for the type class IsString, which is the base for the OverloadedStrings extension.
Well, now I didn't read the error message properly. You have been absolutely right with your analysis.
Instead of giving each element a type you could give the whole list a type: ["a", "b"] :: [T.Text]
Or you could add a helper function: hprintT :: (MonadIO m) => Handle -> TF.Format -> [T.Text] -> m () hprintT = TF.hprint Greetings, Daniel

Thank you for the further tips. The root of my problem, the reason I decided to use that text-format library though, is because I thought Text.Printf is mangling unicode characters because it's working on String and not on Data.Text. However I realized now that even using text-format the unicode characters were still not written correctly in the file (well there was an error saving the file, invalid character, same as with Text.Printf). And I found the correct fix: I must add: hSetEncoding fileH utf8 After opening the file and before writing it in. If I do that, the unicode characters are written OK, and even if I use the usual Text.Printf (and even on windows - on linux where the locale is anyway utf8 it was working from the start). So now I'm wondering should I even use text-format since after all Text.Printf does the job? The author of text-format claims it's written more efficiently but then again I don't believe there is any kind of bottleneck there. Emmanuel On Sun, Oct 21, 2012 at 10:24 AM, Daniel Trstenjak < daniel.trstenjak@gmail.com> wrote:
On Sat, Oct 20, 2012 at 10:34:27PM +0200, Daniel Trstenjak wrote:
The issue arises, because Text and a type of the Json library you're using, both have an instance for the type class IsString, which is the base for the OverloadedStrings extension.
Well, now I didn't read the error message properly. You have been absolutely right with your analysis.
Instead of giving each element a type you could give the whole list a type: ["a", "b"] :: [T.Text]
Or you could add a helper function:
hprintT :: (MonadIO m) => Handle -> TF.Format -> [T.Text] -> m () hprintT = TF.hprint
Greetings, Daniel
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
participants (2)
-
Daniel Trstenjak
-
Emmanuel Touzery