haskellblaze-html

blaze-html, Haskell, correct toHtml usage?


Two things I can't figure out: 1) Without {-# LANGUAGE OverloadedStrings #-} none of the typical code, where pure strings are passed as an arguments for attributes, works; however everything fine as long as that instruction is there. What does it do in this particular case and how safe is it to use in a production code?

2) Following piece of code: (toHtml $ "<script ... ></script>") fails with something I don't quite understand:

Ambiguous type variable ‘a0’ arising from the literal ... prevents the constraint ‘(Data.String.IsString a0)’ from being solved. Probable fix: use a type annotation to specify what ‘a0’ should be. These potential instances exist: instance Data.String.IsString H.AttributeValue -- Defined in ‘blaze-markup-0.8.2.1:Text.Blaze.Internal’ instance Data.String.IsString H.Tag -- Defined in ‘blaze-markup-0.8.2.1:Text.Blaze.Internal’ instance a ~ Char => Data.String.IsString [a] -- Defined in ‘Data.String’ ...plus 10 instances involving out-of-scope types


Solution

    1. In standard Haskell, a string literal like "foo" is always parsed into a value of type String = [Char]. Blaze doesn't use actual String values in most places, instead using its own types like AttributeValue for each semantically different thing. This means that in standard Haskell, without OverloadedStrings, it is impossible to pass string literals to many Blaze functions which expect AttributeValues, Tags, etc. When you set -XOverloadedStrings, GHC will allow a string literal to have type Data.String.IsString p => p instead of String, so you can use a string literal anywhere that some type which has an instance of IsString is expected. This is used by all the "standard" Blaze code. OverloadedStrings is a fairly simple extension---it is basically doing for string literals what Num does for integer literals---and I'm not aware of any large amount of controversy around it. I think that it should be safe for use in production code, and several production codebases use it.

    2. This error message is due to the fact that toHtml is universally quantified over the type of its first argument, with some constraints: toHtml :: ToMarkup a => a -> Html, and---with OverloadedStrings---the type of a string is also a type variable. Basically, GHC knows that the type of the string literal, which will be passed into toHtml needs to be some type, and that type needs to have instances for ToMarkup and IsString, but it doesn't have any way to be sure what that type should be! In this case, it looks like you are probably looking for the string literal to actually have type String here, which you can get by manually annotating the literal: toHtml ("foo" :: String), or by using -XTypeApplications: toHtml @String "foo".