| Copyright | (c) Andy Gill 2001 (c) Oregon Graduate Institute of Science and Technology 2002 |
|---|---|
| License | BSD-style (see the file libraries/base/LICENSE) |
| Maintainer | libraries@haskell.org |
| Stability | stable |
| Portability | portable |
| Safe Haskell | Trustworthy |
| Language | Haskell2010 |
GHC.Internal.Control.Monad.Fix
Contents
Description
Monadic fixpoints.
For a detailed discussion, see Levent Erkok's thesis, Value Recursion in Monadic Computations, Oregon Graduate Institute, 2002.
Documentation
class Monad m => MonadFix (m :: Type -> Type) where Source #
Monads having fixed points with a 'knot-tying' semantics.
Instances of MonadFix should satisfy the following laws:
- Purity
mfix(return. h) =return(fixh)- Left shrinking (or Tightening)
mfix(\x -> a >>= \y -> f x y) = a >>= \y ->mfix(\x -> f x y)- Sliding
, for strictmfix(liftMh . f) =liftMh (mfix(f . h))h.- Nesting
mfix(\x ->mfix(\y -> f x y)) =mfix(\x -> f x x)
This class is used in the translation of the recursive do notation
supported by GHC and Hugs.
Methods
Instances
| MonadFix NonEmpty Source # | Since: base-4.9.0.0 |
| MonadFix Identity Source # | Since: base-4.8.0.0 |
| MonadFix First Source # | Since: base-4.8.0.0 |
| MonadFix Last Source # | Since: base-4.8.0.0 |
| MonadFix Down Source # | Since: base-4.12.0.0 |
| MonadFix Dual Source # | Since: base-4.8.0.0 |
| MonadFix Product Source # | Since: base-4.8.0.0 |
| MonadFix Sum Source # | Since: base-4.8.0.0 |
| MonadFix Par1 Source # | Since: base-4.9.0.0 |
| MonadFix Q Source # | If the function passed to Since: ghc-internal-2.17.0.0 |
| MonadFix IO Source # | Since: base-2.1 |
| MonadFix Maybe Source # | Since: base-2.1 |
| MonadFix Solo Source # | Since: base-4.15 |
| MonadFix [] Source # | Since: base-2.1 |
Defined in GHC.Internal.Control.Monad.Fix | |
| MonadFix (ST s) Source # | Since: base-2.1 |
| MonadFix (Either e) Source # | Since: base-4.3.0.0 |
| MonadFix (ST s) Source # | Since: base-2.1 |
| Monoid a => MonadFix ((,) a) Source # | Since: base-4.21 |
Defined in GHC.Internal.Control.Monad.Fix | |
| MonadFix f => MonadFix (Ap f) Source # | Since: base-4.12.0.0 |
| MonadFix f => MonadFix (Alt f) Source # | Since: base-4.8.0.0 |
| MonadFix f => MonadFix (Rec1 f) Source # | Since: base-4.9.0.0 |
| (MonadFix f, MonadFix g) => MonadFix (f :*: g) Source # | Since: base-4.9.0.0 |
| MonadFix f => MonadFix (M1 i c f) Source # | Since: base-4.9.0.0 |
is the least fixed point of the function fix ff,
i.e. the least defined x such that f x = x.
When f is strict, this means that because, by the definition of strictness,
f ⊥ = ⊥ and such the least defined fixed point of any strict function is ⊥.
Examples
We can write the factorial function using direct recursion as
>>>let fac n = if n <= 1 then 1 else n * fac (n-1) in fac 5120
This uses the fact that Haskell’s let introduces recursive bindings. We can
rewrite this definition using fix,
Instead of making a recursive call, we introduce a dummy parameter rec;
when used within fix, this parameter then refers to fix’s argument, hence
the recursion is reintroduced.
>>>fix (\rec n -> if n <= 1 then 1 else n * rec (n-1)) 5120
Using fix, we can implement versions of repeat as
and fix . (:)cycle as fix . (++)
>>>take 10 $ fix (0:)[0,0,0,0,0,0,0,0,0,0]
>>>map (fix (\rec n -> if n < 2 then n else rec (n - 1) + rec (n - 2))) [1..10][1,1,2,3,5,8,13,21,34,55]
Implementation Details
fixIO :: (a -> IO a) -> IO a Source #
The implementation of mfix for IO.
This operation may fail with:
FixIOExceptionif the function passed tofixIOinspects its argument.
Examples
the IO-action is only executed once. The recursion is only on the values.
>>>take 3 <$> fixIO (\x -> putStr ":D" >> (:x) <$> readLn @Int):D 2 [2,2,2]
If we are strict in the value, just as with fix, we do not get termination:
>>>fixIO (\x -> putStr x >> pure ('x' : x))* hangs forever *
We can tie the knot of a structure within IO using fixIO:
data Node = MkNode Int (IORef Node) foo :: IO () foo = do p <- fixIO (p -> newIORef (MkNode 0 p)) q <- output p r <- output q _ <- output r pure () output :: IORef Node -> IO (IORef Node) output ref = do MkNode x p <- readIORef ref print x pure p
>>>foo0 0 0
Feedback for Arrow
class Arrow a => ArrowLoop (a :: Type -> Type -> Type) where Source #
The loop operator expresses computations in which an output value
is fed back as input, although the computation occurs only once.
It underlies the rec value recursion construct in arrow notation.
loop should satisfy the following laws:
- extension
loop(arrf) =arr(\ b ->fst(fix(\ (c,d) -> f (b,d))))- left tightening
loop(firsth >>> f) = h >>>loopf- right tightening
loop(f >>>firsth) =loopf >>> h- sliding
loop(f >>>arr(id*** k)) =loop(arr(id*** k) >>> f)- vanishing
loop(loopf) =loop(arrunassoc >>> f >>>arrassoc)- superposing
second(loopf) =loop(arrassoc >>>secondf >>>arrunassoc)
where
assoc ((a,b),c) = (a,(b,c)) unassoc (a,(b,c)) = ((a,b),c)
Methods
loop :: a (b, d) (c, d) -> a b c Source #
╭──────────────╮
b │ ╭───╮ │ c
>───┼─────┤ ├────┼───>
│ ┌─┤ ├─┐ │
│ d │ ╰───╯ │ │
│ └───<───┘ │
╰──────────────╯