Skip to content

Instantly share code, notes, and snippets.

@gabejohnson
Last active June 10, 2020 17:07
Show Gist options
  • Save gabejohnson/379a33b09379b0531a6f1a110bbfa110 to your computer and use it in GitHub Desktop.
Save gabejohnson/379a33b09379b0531a6f1a110bbfa110 to your computer and use it in GitHub Desktop.
A DSL for labeled template literals
module Main where
import Prelude
import Effect (Effect)
import Data.Array (snoc)
import Data.Foldable (fold)
import Data.Tuple.Nested (type (/\), (/\))
import TryPureScript (h1, render, text)
main :: Effect Unit
main =
render $ fold
[ h1 (text (show (runTemplate (template "hello " $| 12 |$ " how is it going " $| 13 |$ " buddy")))) ]
data Template a
= TemplatePrefix String
| TemplateInfix (Template a) a
| TemplateSuffix (Template a) String
template :: forall a. String -> Template a
template = TemplatePrefix
infixl 6 TemplateInfix as $|
infixl 6 TemplateSuffix as |$
foo :: Template Int
foo = template "hello " $| 12 |$ " how is it going " $| 13 |$ " buddy"
runTemplate :: forall a. Template a -> (Array String /\ Array a)
runTemplate = go ([] /\ [])
where
go :: (Array String /\ Array a) -> Template a -> (Array String /\ Array a)
go (strs /\ args) = case _ of
TemplatePrefix str -> (strs `snoc` str /\ args)
TemplateInfix template' arg ->
let (strs' /\ args') = go (strs /\ args) template'
in (strs' /\ args' `snoc` arg)
TemplateSuffix template' str ->
let (strs' /\ args') = go (strs /\ args) template'
in (strs' `snoc` str /\ args')
{- In FFI, you could have something like
exports.someTemplateLabelImpl = strs => args => templateLabel(strs, ...args);
and a then in your module
foreign import someTemplateLabelImpl :: forall a. Array String -> Array a -> ?
someTemplateLabel :: forall a. Template a -> ?
someTemplateLabel = uncurry someTemplateLabelImpl <<< runTemplate
-}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment