data Format monoid result f
String formatter, like
printf, but type-safe and composable.
import Text.Formatting (print, s, string)
Build up a
Format, composing with
greeting :: forall r. Format String r (String -> r) greeting = s "Hello " <<< string <<< s "!"
Convert it to a function with
greet :: String -> String greet = print greeting
Then use it:
message1 :: String message1 = greet "Kris" --> message1 == "Hello Kris!"
Or more often, use it directly:
message2 :: String message2 = print greeting "Kris" --> message2 == "Hello Kris!"
What really sets this approach apart from string interpolation,
apart from the type-safety, is that we can freely compose
Formats. Let's extend
greeting with some more arguments:
inbox :: forall r. Format String r (String -> Int -> r) inbox = greeting <<< s " You have " <<< F.int <<< s " new messages."
welcome :: String -> Int -> String welcome = print inbox
Or again, call it in one go:
message3 :: String message3 = print inbox "Kris" 3 --> message3 == "Hello Kris! You have 3 new messages."
A Guide To The Types
As an example, a function that behaves like
printf "%s: %d" would
will have the type signature
Format String r (String -> Int -> r).
This tells you that:
Format String- This is a
Formatthat will eventually yield a
r- This keeps the final type of the formatter open.
(String -> Int -> r)- The formatter takes a
String, then an
Int, and is open to further extension.
Format ((monoid -> result) -> f)
Semigroupoid (Format String)
Note to interested readers:
Formatshould be a
Semigroupoid- and hence composable with
<<<for any format of type
forall m r f. Semigroupoid m => Format m r f
However, I don't know how to persuade PureScript of that. Or even if it's valid to say, "This is a member of that category, provided you meet my extra constraints..."
Nevertheless, for the most common format - the one that yields
Strings, it's composable. And that probably all most people will care about.