Skip to content

Instantly share code, notes, and snippets.

@friedbrice
Last active September 2, 2019 03:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save friedbrice/2ff46b0af91e53d77240e6e2ae5420e4 to your computer and use it in GitHub Desktop.
Save friedbrice/2ff46b0af91e53d77240e6e2ae5420e4 to your computer and use it in GitHub Desktop.
Haskell Kwargs Dream Syntax
-- dream syntax for Haskell kwargs
mkString :: Show a =>
{ pfx :: String, ifx :: String, sfx :: String } -> [a] -> String
mkString { pfx, ifx, sfx } xs =
pfx ++ infixed xs ++ sfx
where
infixed [] = ""
infixed [x] = show x
infixed (x:xs) = prepend x (infixed xs)
prepend x s = show x ++ ifx ++ s
-- you can call `mkString` using record syntax
bracesAndSemicolon :: Show a => [a] -> String
bracesAndSemicolon = mkString { pfx = "{", ifx = ";", sfx = "}" }
-- you can call `mkString` using positional syntax
anglesAndColon :: Show a => [a] -> String
anglesAndColon = mkString "<" ":" ">"
-- you can partially apply the record
parensAndYouPickIfx :: Show a => { ifx :: String } -> [a] -> String
parensAndYouPickIfx = mkString { pfx = "(", sfx = ")" }
-- syntax is purely sugar. core representation of mkString is
--
-- Show a -> String -> String -> String -> [a] -> String
--
-- as such, `{ pfx :: String, ifx :: String, sfx :: String }` is
-- not a type, so no modifications to the type system are needed,
-- only modifications to headers (.hi files) and desugaring step.
-- also along those lines, there are no selectors, you must mach
-- out the named arguments in your function binder (or use
-- positional binding).
--
-- this provides a lightweight alternative to the below patterns:
--
-- type Pfx = String
-- type Ifx = String
-- type Sfx = String
--
-- mkString :: Show a -> Pfx -> Ifx -> Sfx -> [a] -> String
--
-- which introduces extra type-level noise without much dummy-proofing
--
-- and
--
-- newtype Pfx = Pfx String
-- newtype Ifx = Ifx String
-- newtype Sfx = Sfx String
--
-- mkString :: Show a -> Pfx -> Ifx -> Sfx -> [a] -> String
--
-- which provides great dummy-proofing but also adds type-level noise
-- and is kind of onerous to use.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment