{-# LANGUAGE TypeFamilies #-} module Data.Result ( -- * Describing Simulation Results with Type Annotations -- $description Result(..) ) where import Control.DeepSeq import Data.Monoid {- $description #description# Carbon simulations are built up from 'Control.Monad.MonteCarlo' actions. A 'MonteCarlo' action describes how to arrive at an observation, but not how to aggregate observations. This functionality is specified with a type annotation telling Haskell which instance of the type family 'Result' should be used. For example, given a 'MonteCarlo' action, mySim, with type: > mySim :: RandomGen g => MonteCarlo g Bool We get different results based on the instance of 'Result' chosen: > experimentS mySimulation 100 g :: [Bool] > experimentS mySimulation 100 g :: BoolSumm -} -- | Result is the type family used to describe the aggregation techniques to be used in a Monte Carlo simulation. -- Instances of Result should specify the type of a single observation and how to include one. -- The value of a 'Result' without any observations should be specified. -- Additionally, 'Result's should be joinable. -- -- Note that almost all instances of 'Result' will be monoidal. class Result r where -- | The type of a single observation type Obs r :: * -- | How to add a single observation to the result addObs :: r -> Obs r -> r -- | How to join two results together rjoin :: r -> r -> r -- | The value of a result without any observations rzero :: r -- | One common aggregation technique is appending observations to a list. -- In the interest of preventing thunks from building up, we force deep evaluation of observations. instance NFData a => Result [a] where type Obs [a] = a addObs r o = o `deepseq` (o : r) rjoin = mappend rzero = mempty