ghc-internal-9.1500.0: Basic libraries
Copyright(c) Andy Gill 2001
(c) Oregon Graduate Institute of Science and Technology 2002
LicenseBSD-style (see the file libraries/base/LICENSE)
Maintainerlibraries@haskell.org
Stabilitystable
Portabilityportable
Safe HaskellTrustworthy
LanguageHaskell2010

GHC.Internal.Control.Monad.Fix

Description

Monadic fixpoints.

For a detailed discussion, see Levent Erkok's thesis, Value Recursion in Monadic Computations, Oregon Graduate Institute, 2002.

Synopsis

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 (fix h)
Left shrinking (or Tightening)
mfix (\x -> a >>= \y -> f x y) = a >>= \y -> mfix (\x -> f x y)
Sliding
mfix (liftM h . f) = liftM h (mfix (f . h)), for strict 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

mfix :: (a -> m a) -> m a Source #

The fixed point of a monadic computation. mfix f executes the action f only once, with the eventual output fed back as the input. Hence f should not be strict, for then mfix f would diverge.

Instances

Instances details
MonadFix NonEmpty Source #

Since: base-4.9.0.0

Instance details

Defined in GHC.Internal.Control.Monad.Fix

Methods

mfix :: (a -> NonEmpty a) -> NonEmpty a Source #

MonadFix Identity Source #

Since: base-4.8.0.0

Instance details

Defined in GHC.Internal.Control.Monad.Fix

Methods

mfix :: (a -> Identity a) -> Identity a Source #

MonadFix First Source #

Since: base-4.8.0.0

Instance details

Defined in GHC.Internal.Control.Monad.Fix

Methods

mfix :: (a -> First a) -> First a Source #

MonadFix Last Source #

Since: base-4.8.0.0

Instance details

Defined in GHC.Internal.Control.Monad.Fix

Methods

mfix :: (a -> Last a) -> Last a Source #

MonadFix Down Source #

Since: base-4.12.0.0

Instance details

Defined in GHC.Internal.Control.Monad.Fix

Methods

mfix :: (a -> Down a) -> Down a Source #

MonadFix Dual Source #

Since: base-4.8.0.0

Instance details

Defined in GHC.Internal.Control.Monad.Fix

Methods

mfix :: (a -> Dual a) -> Dual a Source #

MonadFix Product Source #

Since: base-4.8.0.0

Instance details

Defined in GHC.Internal.Control.Monad.Fix

Methods

mfix :: (a -> Product a) -> Product a Source #

MonadFix Sum Source #

Since: base-4.8.0.0

Instance details

Defined in GHC.Internal.Control.Monad.Fix

Methods

mfix :: (a -> Sum a) -> Sum a Source #

MonadFix Par1 Source #

Since: base-4.9.0.0

Instance details

Defined in GHC.Internal.Control.Monad.Fix

Methods

mfix :: (a -> Par1 a) -> Par1 a Source #

MonadFix Q Source #

If the function passed to mfix inspects its argument, the resulting action will throw a FixIOException.

Since: ghc-internal-2.17.0.0

Instance details

Defined in GHC.Internal.Control.Monad.Fix

Methods

mfix :: (a -> Q a) -> Q a Source #

MonadFix IO Source #

Since: base-2.1

Instance details

Defined in GHC.Internal.Control.Monad.Fix

Methods

mfix :: (a -> IO a) -> IO a Source #

MonadFix Maybe Source #

Since: base-2.1

Instance details

Defined in GHC.Internal.Control.Monad.Fix

Methods

mfix :: (a -> Maybe a) -> Maybe a Source #

MonadFix Solo Source #

Since: base-4.15

Instance details

Defined in GHC.Internal.Control.Monad.Fix

Methods

mfix :: (a -> Solo a) -> Solo a Source #

MonadFix [] Source #

Since: base-2.1

Instance details

Defined in GHC.Internal.Control.Monad.Fix

Methods

mfix :: (a -> [a]) -> [a] Source #

MonadFix (ST s) Source #

Since: base-2.1

Instance details

Defined in GHC.Internal.Control.Monad.Fix

Methods

mfix :: (a -> ST s a) -> ST s a Source #

MonadFix (Either e) Source #

Since: base-4.3.0.0

Instance details

Defined in GHC.Internal.Control.Monad.Fix

Methods

mfix :: (a -> Either e a) -> Either e a Source #

MonadFix (ST s) Source #

Since: base-2.1

Instance details

Defined in GHC.Internal.Control.Monad.Fix

Methods

mfix :: (a -> ST s a) -> ST s a Source #

Monoid a => MonadFix ((,) a) Source #

Since: base-4.21

Instance details

Defined in GHC.Internal.Control.Monad.Fix

Methods

mfix :: (a0 -> (a, a0)) -> (a, a0) Source #

MonadFix f => MonadFix (Ap f) Source #

Since: base-4.12.0.0

Instance details

Defined in GHC.Internal.Control.Monad.Fix

Methods

mfix :: (a -> Ap f a) -> Ap f a Source #

MonadFix f => MonadFix (Alt f) Source #

Since: base-4.8.0.0

Instance details

Defined in GHC.Internal.Control.Monad.Fix

Methods

mfix :: (a -> Alt f a) -> Alt f a Source #

MonadFix f => MonadFix (Rec1 f) Source #

Since: base-4.9.0.0

Instance details

Defined in GHC.Internal.Control.Monad.Fix

Methods

mfix :: (a -> Rec1 f a) -> Rec1 f a Source #

(MonadFix f, MonadFix g) => MonadFix (f :*: g) Source #

Since: base-4.9.0.0

Instance details

Defined in GHC.Internal.Control.Monad.Fix

Methods

mfix :: (a -> (f :*: g) a) -> (f :*: g) a Source #

MonadFix f => MonadFix (M1 i c f) Source #

Since: base-4.9.0.0

Instance details

Defined in GHC.Internal.Control.Monad.Fix

Methods

mfix :: (a -> M1 i c f a) -> M1 i c f a Source #

fix :: (a -> a) -> a Source #

fix f is the least fixed point of the function f, 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

Expand

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 5
120

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)) 5
120

Using fix, we can implement versions of repeat as fix . (:) and 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

Expand

The current implementation of fix uses structural sharing

fix f = let x = f x in x

A more straightforward but non-sharing version would look like

fix f = f (fix f)

fixIO :: (a -> IO a) -> IO a Source #

The implementation of mfix for IO.

This operation may fail with:

Examples

Expand

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
>>> foo
0
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 (arr f) = arr (\ b -> fst (fix (\ (c,d) -> f (b,d))))
left tightening
loop (first h >>> f) = h >>> loop f
right tightening
loop (f >>> first h) = loop f >>> h
sliding
loop (f >>> arr (id *** k)) = loop (arr (id *** k) >>> f)
vanishing
loop (loop f) = loop (arr unassoc >>> f >>> arr assoc)
superposing
second (loop f) = loop (arr assoc >>> second f >>> arr unassoc)

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 │ ╰───╯ │  │
    │   └───<───┘  │
    ╰──────────────╯

Instances

Instances details
MonadFix m => ArrowLoop (Kleisli m) Source #

Beware that for many monads (those for which the >>= operation is strict) this instance will not satisfy the right-tightening law required by the ArrowLoop class.

Since: base-2.1

Instance details

Defined in GHC.Internal.Control.Monad.Fix

Methods

loop :: Kleisli m (b, d) (c, d) -> Kleisli m b c Source #