random-effin (empty) → 0.1.0.0
raw patch · 4 files changed
+208/−0 lines, 4 filesdep +MonadRandomdep +basedep +effinsetup-changed
Dependencies added: MonadRandom, base, effin, random
Files
- Control/Effect/Random.hs +135/−0
- LICENSE +30/−0
- Setup.hs +2/−0
- random-effin.cabal +41/−0
+ Control/Effect/Random.hs view
@@ -0,0 +1,135 @@+{-# LANGUAGE CPP, DataKinds, DeriveDataTypeable, DeriveFunctor #-}+{-# LANGUAGE ExistentialQuantification, FlexibleContexts, FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses, NoMonomorphismRestriction #-}+{-# LANGUAGE ScopedTypeVariables, StandaloneDeriving, TupleSections #-}+{-# LANGUAGE TypeFamilies, TypeOperators, UndecidableInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+module Control.Effect.Random+ (module System.Random,+ Rand,+ -- * Execution+ runRand, evalRand, evalRandIO,+ -- * Generator functions+ getRandom, getRandomR, getRandoms, getRandomRs,+ fromList, uniform,+ -- * Misc+ withSplit+ ) where+import Control.Arrow (first)+import Control.Effect (Effect, EffectLift, Is, MemberEffect, Row (..))+import Control.Effect (eliminate, intercept, lift, send)+import Control.Monad (liftM)+import Data.Data (Typeable)+import System.Random (Random (..), RandomGen (..), StdGen, newStdGen)+#ifdef MONADRANDOM+import qualified Control.Monad.Random.Class as C+#endif++-- | Random number generator+--+-- Since 0.1.0.0+data Rand g a = RandomGen g => Rand (g -> (a, g))+ deriving (Typeable)++instance Functor (Rand g) where+ fmap g (Rand f) = Rand (first g . f)++type instance Is Rand f = IsRand f+++type family IsRand f where+ IsRand (Rand g) = True+ IsRand f = False++class (RandomGen g, MemberEffect Rand (Rand g) l) => EffectRandom g l+instance (RandomGen g, MemberEffect Rand (Rand g) l) => EffectRandom g l++#ifdef MONADRANDOM+instance EffectRandom g l => C.MonadRandom (Effect l) where+ getRandom = getRandom+ getRandoms = getRandoms+ getRandomR = getRandomR+ getRandomRs = getRandomRs+#endif++-- | Return a randomly-selected value of type a. See 'random' for details.+--+-- Since 0.1.0.0+getRandom :: forall a g l . (Random a, EffectRandom g l) => Effect l a+getRandom = send $ Rand (random :: g -> (a, g))++-- | Return an infinite stream of random values of type a. See 'randoms' for details.+--+-- Since 0.1.0.0+getRandoms :: forall a g l. (Random a, EffectRandom g l) => Effect l [a]+getRandoms = send $ Rand $ \(g :: g) ->+ first randoms $ split g++-- | Return a randomly-selected value of type a in the range @(lo,hi)@. See 'randomR' for details.+--+-- Since 0.1.0.0+getRandomR :: forall a g l. (Random a, EffectRandom g l) => (a, a) -> Effect l a+getRandomR bd = send $ Rand $ \ (g :: g) -> randomR bd g++-- | Return an infinite stream of randomly-selected value+-- of type @a@ in the range @(lo,hi)@. See 'randomRs' for details.+--+-- Since 0.1.0.0+getRandomRs :: forall a g l. (Random a, EffectRandom g l) => (a, a) -> Effect l [a]+getRandomRs bd = send $ Rand $ \(g :: g) -> let (g', g'') = split g in (randomRs bd g', g'')++-- | Sample a random value from a weighted list. The total weight of all elements must not be 0.+--+-- Since 0.1.0.0+fromList :: EffectRandom g l => [(a, Rational)] -> Effect l a+fromList [] = error "Effect.Random.fromList called with empty list"+fromList [(x, _)] = return x+fromList xs = do+ let s = fromRational $ sum $ map snd xs :: Double+ cs = scanl1 (\(_,q) (y,s') -> (y, s'+q)) xs+ p <- liftM toRational (getRandomR (0.0,s))+ return . fst . head $ dropWhile (\(_,q) -> q < p) cs++-- | Sample a value from a uniform distribution of a list of elements.+--+-- Since 0.1.0.0+uniform :: (EffectRandom g l) => [a] -> Effect l a+uniform xs = fromList $ map (flip (,) 1) xs++-- | Run a computation with random numbers+--+-- Since 0.1.0.0+runRand :: forall a l g. RandomGen g+ => g -- ^ initial internal random generator+ -> Effect (Rand g :+ l) a -- ^ Effectect using random numbers+ -> Effect l (a, g)+runRand g0 act = eliminate ret handle act g0+ where+ ret a g = return (a, g)+ handle :: Rand g (g -> Effect l (a, g)) -> g -> Effect l (a, g)+ handle (Rand tog) g = do+ let (cont, g') = tog g+ cont g'++-- | Run a computation with random numbers, discarding the final generator.+--+-- Since 0.1.0.0+evalRand :: RandomGen g => g -> Effect (Rand g :+ l) a -> Effect l a+evalRand g = liftM fst . runRand g++-- | Run a computation with random numbers, discarding the final generator.+--+-- Since 0.1.0.0+evalRandIO :: EffectLift IO l => Effect (Rand StdGen :+ l) a -> Effect l a+evalRandIO eff = do+ g <- lift newStdGen+ evalRand g eff++-- | Split the current generator and execute the given computation with it.+--+-- Since 0.1.0.0+withSplit :: forall g l a. EffectRandom g l => Effect l a -> Effect l a+withSplit eff = do+ g <- send $ Rand split+ let run (Rand fromg) = fst $ fromg (g :: g)+ intercept return run eff
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2014, Hiromi ISHII++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Hiromi ISHII nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ random-effin.cabal view
@@ -0,0 +1,41 @@+-- Initial random-eff.cabal generated by cabal init. For further +-- documentation, see http://haskell.org/cabal/users-guide/++name: random-effin+version: 0.1.0.0+synopsis: A simple random generator library for effin+description: A simple random generator library for effin+license: BSD3+license-file: LICENSE+author: Hiromi ISHII+maintainer: konn.jinro_at_gmail.com+copyright: 2014 (c) Hiromi ISHII+category: Control, Effect+build-type: Simple+-- extra-source-files: examples/*.hs+cabal-version: >=1.10++source-repository head+ type: git+ location: git://github.com/konn/random-effin.git++flag MonadRandom+ description: Enable MonadRandom instances+ default: False++library+ if flag(MonadRandom)+ build-depends: MonadRandom >= 0.3 && < 0.4+ cpp-options: -DMONADRANDOM+ exposed-modules: Control.Effect.Random+ other-extensions: DeriveDataTypeable,+ DeriveFunctor,+ ExistentialQuantification,+ FlexibleContexts,+ MultiParamTypeClasses,+ NoMonomorphismRestriction,+ ScopedTypeVariables+ build-depends: base >=4 && <5+ , effin >=0.2 && <0.3+ , random >=1.0 && <1.1+ default-language: Haskell2010