Zemyla

MonadFix instance for ReadP

Jul 22nd, 2026
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. errMfix :: a
  2. errMfix = errorWithoutStackTrace "mfix (ReadP): loop detected"
  3. {-# NOINLINE errMfix #-}
  4.  
  5. instance MonadFix ReadP where
  6.   mfix f = R (\k -> Look (fixup f 0 k)) where
  7.     toP g a = case g a of R m -> m pure
  8.     {-# INLINE toP #-}
  9.  
  10.     skip :: Int -> P b -> P b
  11.     skip 0 p = p
  12.     skip n p = Get $ const $ skip (n - 1) p
  13.  
  14.     unwrapM Nothing = errMfix
  15.     unwrapM (Just (_, a)) = a
  16.     {-# INLINE unwrapM #-}
  17.  
  18.     fixup :: (a -> ReadP a) -> Int -> (a -> P b) -> String -> P b
  19.     fixup _ n _ _ | n `seq` False = undefined
  20.     fixup f n k s = let
  21.       ms = probeM n 0 (toP f (unwrapM ms)) s
  22.       in case ms of
  23.         Nothing -> Fail
  24.         Just (sk, a) -> skip sk (k a) <|> fixup f (n + 1) k s
  25.  
  26.     probeM n sk _ _ | n `seq` sk `seq` False = undefined
  27.     probeM n sk (Get f) (c:s) = probeM n (sk + 1) (f c) s
  28.     probeM n sk (Look f) s = probeM n sk (f s) s
  29.     probeM n sk (Result a p) s
  30.       | n == 0 = Just (sk, a)
  31.       | otherwise = probeM (n - 1) sk p s
  32.     probeM n sk (Final (r :| rs)) _ = findF n (r:rs) where
  33.       findF _ [] = Nothing
  34.       findF 0 ((a, _):_) = Just (sk, a)
  35.       findF n (_:rs) = findF (n - 1) rs
  36.     probeM _ _ _ _ = Nothing
  37.   {-# INLINE mfix #-}
Advertisement
Add Comment
Please, Sign In to add comment