1
1
mirror of https://github.com/github/semantic.git synced 2024-12-22 14:21:31 +03:00

🔥 For, compute fors as folds.

This commit is contained in:
Rob Rix 2017-03-09 15:34:02 -05:00
parent b81959ac72
commit 5a7cd8d6ab

View File

@ -15,14 +15,9 @@ data State s a where
Get :: State s s Get :: State s s
Put :: s -> State s () Put :: s -> State s ()
data For a where
For :: [a] -> For a
Continue :: For a
data StepF a where data StepF a where
M :: MyersF a -> StepF a M :: MyersF a -> StepF a
S :: State MyersState a -> StepF a S :: State MyersState a -> StepF a
F :: For a -> StepF a
type Myers = Freer StepF type Myers = Freer StepF
@ -40,14 +35,14 @@ decompose :: MyersF a -> Myers a
decompose myers = case myers of decompose myers = case myers of
SES {} -> return [] SES {} -> return []
MiddleSnake as bs -> MiddleSnake as bs -> fmap (fromMaybe (error "bleah")) $
for [0..maxD] $ \ d -> do for [0..maxD] $ \ d -> do
for [negate d, negate d + 2 .. d] $ \ k -> do for [negate d, negate d + 2 .. d] $ \ k -> do
forwardEndpoint <- findDPath Forward (EditDistance d) (Diagonal k) forwardEndpoint <- findDPath Forward (EditDistance d) (Diagonal k)
backwardV <- gets backward backwardV <- gets backward
let reverseEndpoint = backwardV `at` (maxD + k) let reverseEndpoint = backwardV `at` (maxD + k)
if odd delta && k `inInterval` (delta - pred d, delta + pred d) && overlaps forwardEndpoint reverseEndpoint if odd delta && k `inInterval` (delta - pred d, delta + pred d) && overlaps forwardEndpoint reverseEndpoint
then return (Snake reverseEndpoint forwardEndpoint, EditDistance $ 2 * d - 1) then return (Just (Snake reverseEndpoint forwardEndpoint, EditDistance $ 2 * d - 1))
else continue else continue
for [negate d, negate d + 2 .. d] $ \ k -> do for [negate d, negate d + 2 .. d] $ \ k -> do
@ -55,7 +50,7 @@ decompose myers = case myers of
forwardV <- gets forward forwardV <- gets forward
let forwardEndpoint = forwardV `at` (maxD + k + delta) let forwardEndpoint = forwardV `at` (maxD + k + delta)
if even delta && k `inInterval` (negate d, d) && overlaps forwardEndpoint reverseEndpoint if even delta && k `inInterval` (negate d, d) && overlaps forwardEndpoint reverseEndpoint
then return (Snake reverseEndpoint forwardEndpoint, EditDistance $ 2 * d) then return (Just (Snake reverseEndpoint forwardEndpoint, EditDistance $ 2 * d))
else continue else continue
where ceilDiv = (uncurry (+) .) . divMod where ceilDiv = (uncurry (+) .) . divMod
@ -64,6 +59,11 @@ decompose myers = case myers of
delta = n - m delta = n - m
maxD = (m + n) `ceilDiv` 2 maxD = (m + n) `ceilDiv` 2
for :: [a] -> (a -> Myers (Maybe b)) -> Myers (Maybe b)
for all run = foldr (\ a b -> (<|>) <$> run a <*> b) (return Nothing) all
continue = return Nothing
FindDPath {} -> return (Endpoint 0 0) FindDPath {} -> return (Endpoint 0 0)
@ -72,12 +72,6 @@ decompose myers = case myers of
findDPath :: Direction -> EditDistance -> Diagonal -> Myers Endpoint findDPath :: Direction -> EditDistance -> Diagonal -> Myers Endpoint
findDPath direction d k = M (FindDPath direction d k) `Then` return findDPath direction d k = M (FindDPath direction d k) `Then` return
for :: [a] -> (a -> Myers b) -> Myers b
for all run = F (For all) `Then` run
continue :: Myers a
continue = F Continue `Then` return
-- Implementation details -- Implementation details