-- | Miscellaneous utility functions
module Data.Generics.Fixplate.Misc where

--------------------------------------------------------------------------------

import Data.Traversable

--------------------------------------------------------------------------------

mapAccumL_ :: Traversable f => (a -> b -> (a, c)) -> a -> f b -> f c
mapAccumL_ f x t = snd (mapAccumL f x t)

--------------------------------------------------------------------------------
        
data Two a b 
  =  Empty 
  |  One a
  |  Two b

--------------------------------------------------------------------------------

unsafe :: (a -> Maybe b) -> String -> a -> b
unsafe safe msg loc = case safe loc of
  Just new -> new
  Nothing  -> error msg
  
--------------------------------------------------------------------------------

app_prec :: Int
app_prec = 10

--------------------------------------------------------------------------------

(<#>) :: (a -> b) -> (c -> d) -> (a,c) -> (b,d)
(f <#> g) (x,y) = (f x, g y)

--------------------------------------------------------------------------------

tillNothing :: (a -> Maybe a) -> a -> a
tillNothing f = go where 
  go x = case f x of { Nothing -> x ; Just y -> go y }
  
chain :: [a -> Maybe a] -> a -> Maybe a
chain [] x = return x
chain (f:fs) x = (f x) >>= chain fs 
  
chainJust :: [a -> Maybe a] -> a -> a
chainJust fs x = case chain fs x of
  Nothing -> error "chainJust: Nothing"
  Just y  -> y
  
--------------------------------------------------------------------------------  

iterateN :: Int -> (a -> a) -> a -> a
iterateN n f = go n where 
  go 0 x = x
  go n x = go (n-1) (f x)

--------------------------------------------------------------------------------