GitXplorerGitXplorer
M

backtrack

public
1 stars
0 forks
0 issues

Commits

List of commits on branch master.
Verified
fe852fb79d8be4e971fe33e01442d62b4fcf0182

Update README.md

committed 6 years ago
Verified
a555177d09da0dde8f45879d4311811adb0ddeff

Update README.md

committed 6 years ago
Verified
b157a3a55c1953f0b62b8b3a11ba3c4b1268b051

Update example.hs

committed 6 years ago
Verified
1d8637af8b6e3d40ce016555cb1c62a96c09ae3b

Update README.md

committed 6 years ago
Verified
2b6ab05f6b7431d8b4171ff6d7fe3687a7df255a

Rename example to example.hs

committed 6 years ago
Verified
54b8858991b624e58b6215b8d9f3a60069d27fc6

Create example

committed 6 years ago

README

The README file for this repository.

backtrack

Racket-style pattern matching failure continuation for Haskell

Haskell allows guards in pattern matches like the following:

case e of
  Div e (Const n) | n <> 0 -> [...]
  [...]

where Div e (Const n) only matches if n is non-zero. If the guard fails, the remaining patterns are tried. But these guards have to be pure expressions. Racket, on the other hand, exposes a continuation that allows for general computation to happen to decide, if the pattern matches:

> (define (m x)
    (match x
      [(list a b c)
       (=> exit)
       (f x exit)]
      [(list a b c) 'sum-is-not-six]))
> (define (f x exit)
    (if (= 6 (apply + x))
        'sum-is-six
        (exit)))
> (m '(1 2 3))
'sum-is-six

> (m '(2 3 4))
'sum-is-not-six

Using #? from this library we can implement the same in Haskell using TemplateHaskell:

m :: (Num a, Monad m, Eq a) => [a] -> m String
m x =
  $((#?)
     [| case x of
         [a, b, c] -> \exit -> f x exit
         [a, b, c] -> \_ -> return "sum is not six"
      |])

f :: (Eq a, Num a, Monad m) => [a] -> m String -> m String
f x exit =
  if 6 == sum x then return "sum is six"
  else exit

But unlike regular guards, #? allows for arbitrary monadic effects:

example :: IO ()
example = do
  x <-
    $((#?)
      [| case () of
            () -> \k -> do
              liftIO $ putStrLn "Do you want to match the first case?"
              liftIO getLine >>= \case
                "yes" -> return "First case"
                "no" -> k
            () -> \k -> do
              liftIO $ putStrLn "Do you want to match the second case?"
              liftIO getLine >>= \case
                "yes" -> return "Second case"
                "no" -> k
        |])
  putStrLn x