packages feed

hakaru 0.1.4 → 0.3.0

raw patch · 82 files changed

+26228/−1427 lines, 82 filesdep +ansi-terminaldep +filepathdep +indentation-parsecdep −aesondep −arraydep −bytestringdep ~Cabaldep ~HUnitdep ~QuickChecknew-component:exe:compilenew-component:exe:densitynew-component:exe:disintegratenew-component:exe:hakarunew-component:exe:hkcnew-component:exe:mhnew-component:exe:momijinew-component:exe:normalizenew-component:exe:prettynew-component:exe:simplifyPVP ok

version bump matches the API change (PVP)

Dependencies added: ansi-terminal, filepath, indentation-parsec, mtl, optparse-applicative, process, semigroups

Dependencies removed: aeson, array, bytestring, cassava, criterion, deepseq, hmatrix, monad-loops, parallel, random, statistics, test-framework, test-framework-hunit, test-framework-quickcheck2, zlib

Dependency ranges changed: Cabal, HUnit, QuickCheck, base, ghc-prim, hakaru, integration, logfloat, math-functions, primitive, text, transformers, vector

API changes (from Hackage documentation)

- Language.Hakaru.Arrow: type (~~>) a b = a -> Dist b
- Language.Hakaru.Distribution: bern :: Double -> Dist Bool
- Language.Hakaru.Distribution: beta :: Double -> Double -> Dist Double
- Language.Hakaru.Distribution: betaLogDensity :: Double -> Double -> Double -> Double
- Language.Hakaru.Distribution: beta_rng :: PrimMonad m => Double -> Double -> PRNG m -> m Double
- Language.Hakaru.Distribution: categorical :: Eq a => [(a, Double)] -> Dist a
- Language.Hakaru.Distribution: categoricalLogDensity :: (Eq b, Floating a) => [(b, a)] -> b -> a
- Language.Hakaru.Distribution: categoricalSample :: (Num b, Ord b, PrimMonad m, Variate b) => [(t, b)] -> PRNG m -> m t
- Language.Hakaru.Distribution: choose :: PrimMonad m => Mixture k -> PRNG m -> m (k, Prob)
- Language.Hakaru.Distribution: chooseIndex :: PrimMonad m => [Double] -> PRNG m -> m Int
- Language.Hakaru.Distribution: dirac :: Eq a => a -> Dist a
- Language.Hakaru.Distribution: dirichletLogDensity :: [Double] -> [Double] -> Double
- Language.Hakaru.Distribution: dirichlet_rng :: PrimMonad m => Int -> Double -> PRNG m -> m [Double]
- Language.Hakaru.Distribution: gamma :: Double -> Double -> Dist Double
- Language.Hakaru.Distribution: gammaLogDensity :: Double -> Double -> Double -> Double
- Language.Hakaru.Distribution: gamma_rng :: PrimMonad m => Double -> Double -> PRNG m -> m Double
- Language.Hakaru.Distribution: laplace :: Double -> Double -> Dist Double
- Language.Hakaru.Distribution: laplaceLogDensity :: Floating a => a -> a -> a -> a
- Language.Hakaru.Distribution: laplace_rng :: PrimMonad m => Double -> Double -> PRNG m -> m Double
- Language.Hakaru.Distribution: lnFact :: Int -> Double
- Language.Hakaru.Distribution: mapFst :: (t -> s) -> (t, u) -> (s, u)
- Language.Hakaru.Distribution: marsaglia :: (Variate a, Ord a, Floating a, PrimMonad m) => PRNG m -> m (a, a)
- Language.Hakaru.Distribution: normal :: Double -> Double -> Dist Double
- Language.Hakaru.Distribution: normalLogDensity :: Floating a => a -> a -> a -> a
- Language.Hakaru.Distribution: normal_rng :: (Real a, Floating a, Variate a, PrimMonad m) => a -> a -> PRNG m -> m a
- Language.Hakaru.Distribution: poisson :: Double -> Dist Int
- Language.Hakaru.Distribution: poisson_rng :: PrimMonad m => Double -> PRNG m -> m Int
- Language.Hakaru.Distribution: uniform :: Double -> Double -> Dist Double
- Language.Hakaru.Distribution: uniformD :: (Ix a, Variate a) => a -> a -> Dist a
- Language.Hakaru.ImportanceSampler: Measure :: ([Cond] -> Sampler (a, [Cond])) -> Measure a
- Language.Hakaru.ImportanceSampler: bind :: Measure a -> (a -> Measure b) -> Measure b
- Language.Hakaru.ImportanceSampler: condition :: Eq b => Measure (a, b) -> b -> Measure a
- Language.Hakaru.ImportanceSampler: conditioned :: Typeable a => Dist a -> Measure a
- Language.Hakaru.ImportanceSampler: empiricalMeasure :: (PrimMonad m, Ord a) => Int -> Measure a -> [Cond] -> m (Mixture a)
- Language.Hakaru.ImportanceSampler: factor :: Prob -> Measure ()
- Language.Hakaru.ImportanceSampler: finish :: Mixture (a, [Cond]) -> Mixture a
- Language.Hakaru.ImportanceSampler: instance Monad Measure
- Language.Hakaru.ImportanceSampler: logit :: Floating a => a -> a
- Language.Hakaru.ImportanceSampler: newtype Measure a
- Language.Hakaru.ImportanceSampler: sample :: Measure a -> [Cond] -> IO [(a, Prob)]
- Language.Hakaru.ImportanceSampler: unMeasure :: Measure a -> [Cond] -> Sampler (a, [Cond])
- Language.Hakaru.ImportanceSampler: unconditioned :: Typeable a => Dist a -> Measure a
- Language.Hakaru.ImportanceSampler: updateMixture :: Typeable a => Cond -> Dist a -> Sampler a
- Language.Hakaru.Lambda: app :: (a -> b) -> a -> b
- Language.Hakaru.Lambda: dbl :: Double -> Double
- Language.Hakaru.Lambda: fix :: ((a -> b) -> (a -> b)) -> (a -> b)
- Language.Hakaru.Lambda: ifThenElse :: Bool -> a -> a -> a
- Language.Hakaru.Lambda: lam :: (a -> b) -> (a -> b)
- Language.Hakaru.Lambda: lit :: Eq a => a -> a
- Language.Hakaru.Metropolis: DBEntry :: XRP -> LL -> Visited -> Observed -> DBEntry
- Language.Hakaru.Metropolis: Measure :: (Name -> Sampler a) -> Measure a
- Language.Hakaru.Metropolis: S :: Database -> {-# UNPACK #-} !LL2 -> [Cond] -> SamplerState
- Language.Hakaru.Metropolis: XRP :: (Density e, Dist e) -> XRP
- Language.Hakaru.Metropolis: app :: Measure (a -> b) -> Measure a -> Measure b
- Language.Hakaru.Metropolis: bind :: Measure a -> (a -> Measure b) -> Measure b
- Language.Hakaru.Metropolis: cnds :: SamplerState -> [Cond]
- Language.Hakaru.Metropolis: condition :: Eq b => Measure (a, b) -> b -> Measure a
- Language.Hakaru.Metropolis: conditioned :: Typeable a => Dist a -> Measure a
- Language.Hakaru.Metropolis: data DBEntry
- Language.Hakaru.Metropolis: data SamplerState
- Language.Hakaru.Metropolis: data XRP
- Language.Hakaru.Metropolis: factor :: LL -> Measure ()
- Language.Hakaru.Metropolis: initialStep :: Measure a -> [Cond] -> PRNG IO -> IO (a, Database, LL, LL, LL)
- Language.Hakaru.Metropolis: instance Applicative Measure
- Language.Hakaru.Metropolis: instance Functor Measure
- Language.Hakaru.Metropolis: instance Monad Measure
- Language.Hakaru.Metropolis: instance Typeable Measure
- Language.Hakaru.Metropolis: ldb :: SamplerState -> Database
- Language.Hakaru.Metropolis: llh2 :: SamplerState -> {-# UNPACK #-} !LL2
- Language.Hakaru.Metropolis: llhd :: DBEntry -> LL
- Language.Hakaru.Metropolis: mcmc :: Typeable a => Measure a -> [Cond] -> IO [a]
- Language.Hakaru.Metropolis: newtype Measure a
- Language.Hakaru.Metropolis: observed :: DBEntry -> Observed
- Language.Hakaru.Metropolis: resample :: PrimMonad m => Name -> Database -> Observed -> XRP -> PRNG m -> m (Database, LL, LL, LL)
- Language.Hakaru.Metropolis: return_ :: a -> Measure a
- Language.Hakaru.Metropolis: run :: Measure a -> [Cond] -> IO (a, Database, LL)
- Language.Hakaru.Metropolis: sample :: Typeable a => Measure a -> [Cond] -> IO [(a, Double)]
- Language.Hakaru.Metropolis: sapp :: (Sampler (a -> b)) -> Sampler a -> Sampler b
- Language.Hakaru.Metropolis: sbind :: Sampler a -> (a -> Sampler b) -> Sampler b
- Language.Hakaru.Metropolis: smap :: (a -> b) -> Sampler a -> Sampler b
- Language.Hakaru.Metropolis: sreturn :: a -> Sampler a
- Language.Hakaru.Metropolis: traceUpdate :: PrimMonad m => Measure a -> Database -> [Cond] -> PRNG m -> m (a, Database, LL, LL, LL)
- Language.Hakaru.Metropolis: transition :: Typeable a => Measure a -> [Cond] -> a -> Database -> LL -> PRNG IO -> IO [a]
- Language.Hakaru.Metropolis: type Database = Map Name DBEntry
- Language.Hakaru.Metropolis: type DistVal = Dynamic
- Language.Hakaru.Metropolis: type LL = LogLikelihood
- Language.Hakaru.Metropolis: type LL2 = (LL, LL)
- Language.Hakaru.Metropolis: type Name = [Subloc]
- Language.Hakaru.Metropolis: type Observed = Bool
- Language.Hakaru.Metropolis: type Sampler a = PrimMonad m => SamplerState -> PRNG m -> m (a, SamplerState)
- Language.Hakaru.Metropolis: type Subloc = Int
- Language.Hakaru.Metropolis: type Visited = Bool
- Language.Hakaru.Metropolis: unMeasure :: Measure a -> Name -> Sampler a
- Language.Hakaru.Metropolis: unXRP :: Typeable a => XRP -> Maybe (Density a, Dist a)
- Language.Hakaru.Metropolis: unconditioned :: Typeable a => Dist a -> Measure a
- Language.Hakaru.Metropolis: updateLogLikelihood :: LL2 -> LL2 -> LL2
- Language.Hakaru.Metropolis: updateXRP :: Typeable a => Name -> Cond -> Dist a -> Sampler a
- Language.Hakaru.Metropolis: vis :: DBEntry -> Visited
- Language.Hakaru.Metropolis: xrp :: DBEntry -> XRP
- Language.Hakaru.Mixture: Mixture :: Map k Prob -> Mixture k
- Language.Hakaru.Mixture: cross :: Ord k => (k1 -> k2 -> k) -> Mixture k1 -> Mixture k2 -> Mixture k
- Language.Hakaru.Mixture: empty :: Mixture k
- Language.Hakaru.Mixture: instance Ord k => Monoid (Mixture k)
- Language.Hakaru.Mixture: instance Show k => Show (Mixture k)
- Language.Hakaru.Mixture: mmap :: Ord k2 => (k1 -> k2) -> Mixture k1 -> Mixture k2
- Language.Hakaru.Mixture: mnull :: Mixture k -> Bool
- Language.Hakaru.Mixture: mode :: Mixture k -> (k, Prob)
- Language.Hakaru.Mixture: newtype Mixture k
- Language.Hakaru.Mixture: point :: k -> Prob -> Mixture k
- Language.Hakaru.Mixture: scale :: Prob -> Mixture k -> Mixture k
- Language.Hakaru.Mixture: toList :: Mixture k -> [(k, Prob)]
- Language.Hakaru.Mixture: type Prob = LogFloat
- Language.Hakaru.Mixture: unMixture :: Mixture k -> Map k Prob
- Language.Hakaru.Sampler: deterministic :: Mixture a -> Sampler a
- Language.Hakaru.Sampler: sbind :: Sampler a -> (a -> Sampler b) -> Sampler b
- Language.Hakaru.Sampler: smap :: (a -> b) -> Sampler a -> Sampler b
- Language.Hakaru.Sampler: type Sampler a = PrimMonad m => PRNG m -> m (Mixture a)
- Language.Hakaru.Symbolic: Back :: Pos
- Language.Hakaru.Symbolic: Front :: Pos
- Language.Hakaru.Symbolic: Maple :: (Pos -> VarCounter -> String) -> Maple a
- Language.Hakaru.Symbolic: add, mul, minus :: SymbComp repr => repr a -> repr a -> repr a
- Language.Hakaru.Symbolic: bind :: MeasMonad repr => repr (Measure a) -> (repr a -> repr (Measure b)) -> repr (Measure b)
- Language.Hakaru.Symbolic: binder :: (String -> String -> Maybe String) -> (String -> String -> VarCounter -> Maybe String) -> String -> Maple a -> Maple a -> Maple (Dist a)
- Language.Hakaru.Symbolic: bool :: BoolComp repr => Bool -> repr Bool
- Language.Hakaru.Symbolic: class BoolComp repr
- Language.Hakaru.Symbolic: class Conditioning repr
- Language.Hakaru.Symbolic: class Distrib repr
- Language.Hakaru.Symbolic: class IntComp repr
- Language.Hakaru.Symbolic: class MeasMonad repr
- Language.Hakaru.Symbolic: class RealComp repr
- Language.Hakaru.Symbolic: class SymbComp repr
- Language.Hakaru.Symbolic: conditioned, unconditioned :: Conditioning repr => repr (Dist a) -> repr (Measure a)
- Language.Hakaru.Symbolic: d2m :: Maple (Dist a) -> Maple (Measure a)
- Language.Hakaru.Symbolic: data Dist a
- Language.Hakaru.Symbolic: data Exact
- Language.Hakaru.Symbolic: data Measure a
- Language.Hakaru.Symbolic: data Pos
- Language.Hakaru.Symbolic: data Prob
- Language.Hakaru.Symbolic: data Real
- Language.Hakaru.Symbolic: exp :: RealComp repr => repr Real -> repr Real -> repr Real
- Language.Hakaru.Symbolic: exp1 :: Maple (Measure Real)
- Language.Hakaru.Symbolic: exp2 :: Maple (Measure Real)
- Language.Hakaru.Symbolic: exp3 :: Maple (Measure Real)
- Language.Hakaru.Symbolic: exp4 :: Maple (Measure Real)
- Language.Hakaru.Symbolic: infixPr :: String -> (String -> String -> String)
- Language.Hakaru.Symbolic: instance BoolComp Maple
- Language.Hakaru.Symbolic: instance Conditioning Maple
- Language.Hakaru.Symbolic: instance Distrib Maple
- Language.Hakaru.Symbolic: instance IntComp Maple
- Language.Hakaru.Symbolic: instance MeasMonad Maple
- Language.Hakaru.Symbolic: instance RealComp Maple
- Language.Hakaru.Symbolic: instance SymbComp Maple
- Language.Hakaru.Symbolic: int :: IntComp repr => Integer -> repr Integer
- Language.Hakaru.Symbolic: lift :: Maple Integer -> Maple Real
- Language.Hakaru.Symbolic: liftA1 :: (String -> String) -> Maple a -> Maple a
- Language.Hakaru.Symbolic: liftA1M :: (String -> String) -> Maple a -> Maple (Measure a)
- Language.Hakaru.Symbolic: liftA2 :: (String -> String -> String) -> Maple a -> Maple a -> Maple a
- Language.Hakaru.Symbolic: liftA2aba :: (String -> String -> String) -> Maple a -> Maple b -> Maple a
- Language.Hakaru.Symbolic: liftA2baa :: (String -> String -> String) -> Maple b -> Maple a -> Maple a
- Language.Hakaru.Symbolic: mkPr :: String -> (String -> String)
- Language.Hakaru.Symbolic: name :: String -> VarCounter -> String
- Language.Hakaru.Symbolic: newtype Maple a
- Language.Hakaru.Symbolic: pow :: SymbComp repr => repr Real -> repr Integer -> repr Real
- Language.Hakaru.Symbolic: pure :: Show (MPL a) => MPL a -> Maple a
- Language.Hakaru.Symbolic: real :: RealComp repr => Rational -> repr Real
- Language.Hakaru.Symbolic: reify :: Read a => Pos -> VarCounter -> Maple a -> a
- Language.Hakaru.Symbolic: ret :: MeasMonad repr => repr a -> repr (Measure a)
- Language.Hakaru.Symbolic: scale :: SymbComp repr => repr Integer -> repr Real -> repr Real
- Language.Hakaru.Symbolic: sqrt, sin, cos :: RealComp repr => repr Real -> repr Real
- Language.Hakaru.Symbolic: test :: String
- Language.Hakaru.Symbolic: test2 :: String
- Language.Hakaru.Symbolic: test3 :: String
- Language.Hakaru.Symbolic: test4 :: String
- Language.Hakaru.Symbolic: type VarCounter = Int
- Language.Hakaru.Symbolic: unMaple :: Maple a -> Pos -> VarCounter -> String
- Language.Hakaru.Symbolic: uniform, normal :: Distrib repr => repr Real -> repr Real -> repr (Dist Real)
- Language.Hakaru.Symbolic: uniformD :: Distrib repr => repr Integer -> repr Integer -> repr (Dist Integer)
- Language.Hakaru.Symbolic: var :: String -> VarCounter -> Maple a
- Language.Hakaru.Symbolic: view :: Maple a -> String
- Language.Hakaru.Types: Discrete :: !a -> Density a
- Language.Hakaru.Types: Dist :: (Density a -> LogLikelihood) -> (forall m. PrimMonad m => PRNG m -> m (Density a)) -> Dist a
- Language.Hakaru.Types: Lebesgue :: !a -> Density a
- Language.Hakaru.Types: data Density a
- Language.Hakaru.Types: data Dist a
- Language.Hakaru.Types: distSample :: Dist a -> forall m. PrimMonad m => PRNG m -> m (Density a)
- Language.Hakaru.Types: fromDensity :: Density t -> t
- Language.Hakaru.Types: fromDiscrete :: Density t -> t
- Language.Hakaru.Types: fromLebesgue :: Density t -> t
- Language.Hakaru.Types: instance Typeable Density
- Language.Hakaru.Types: instance Typeable Dist
- Language.Hakaru.Types: logDensity :: Dist a -> Density a -> LogLikelihood
- Language.Hakaru.Types: type Cond = Maybe Dynamic
- Language.Hakaru.Types: type LogLikelihood = Double
- Language.Hakaru.Types: type PRNG m = Gen (PrimState m)
- Language.Hakaru.Util.Coda: effectiveSampleSize :: [Double] -> Double
- Language.Hakaru.Util.Coda: meanVariance :: Fractional a => [a] -> (a, a)
- Language.Hakaru.Util.Csv: (:::) :: a -> b -> (:::) a b
- Language.Hakaru.Util.Csv: data (:::) a b
- Language.Hakaru.Util.Csv: decodeFile :: FromRecord a => FilePath -> IO [a]
- Language.Hakaru.Util.Csv: decodeFileStream :: FromRecord a => FilePath -> IO [a]
- Language.Hakaru.Util.Csv: decodeGZipFile :: FromRecord a => FilePath -> IO [a]
- Language.Hakaru.Util.Csv: decodeGZipFileStream :: FromRecord a => FilePath -> IO [a]
- Language.Hakaru.Util.Csv: instance (Eq a, Eq b) => Eq (a ::: b)
- Language.Hakaru.Util.Csv: instance (FromField a, FromRecord b) => FromRecord (a ::: b)
- Language.Hakaru.Util.Csv: instance (Ord a, Ord b) => Ord (a ::: b)
- Language.Hakaru.Util.Csv: instance (Read a, Read b) => Read (a ::: b)
- Language.Hakaru.Util.Csv: instance (Show a, Show b) => Show (a ::: b)
- Language.Hakaru.Util.Csv: instance (ToField a, ToRecord b) => ToRecord (a ::: b)
- Language.Hakaru.Util.Extras: extract :: Seq a -> Int -> Maybe (Seq a, a)
- Language.Hakaru.Util.Extras: l2Norm :: Floating a => [a] -> a
- Language.Hakaru.Util.Extras: pairs :: [a] -> [(a, a)]
- Language.Hakaru.Util.Extras: pieces :: Seq a -> Seq Int -> [Seq a]
- Language.Hakaru.Util.Extras: randomElems :: Ord a => Seq a -> Int -> IO (Seq a)
- Language.Hakaru.Util.Extras: randomElemsTR :: Ord a => Seq a -> Seq a -> GenIO -> Int -> IO (Seq a)
- Language.Hakaru.Util.Extras: randomExtract :: Seq a -> GenIO -> IO (Maybe (Seq a, a))
- Language.Hakaru.Util.Extras: randomPieces :: Int -> Seq a -> IO [Seq a]
- Language.Hakaru.Util.Visual: batchPrint :: Show a => Int -> [a] -> IO ()
- Language.Hakaru.Util.Visual: plot :: Show a => [a] -> String -> IO ()
- Language.Hakaru.Util.Visual: viz :: ToJSON a => Int -> [String] -> [[a]] -> IO ()
- Language.Hakaru.Util.Visual: viz' :: ToJSON a => Int -> Int -> Int -> [String] -> [[a]] -> IO ()
+ Data.Number.Nat: MaxNat :: Nat -> MaxNat
+ Data.Number.Nat: [unMaxNat] :: MaxNat -> Nat
+ Data.Number.Nat: data Nat
+ Data.Number.Nat: fromNat :: Nat -> Int
+ Data.Number.Nat: instance GHC.Base.Monoid Data.Number.Nat.MaxNat
+ Data.Number.Nat: instance GHC.Classes.Eq Data.Number.Nat.Nat
+ Data.Number.Nat: instance GHC.Classes.Ord Data.Number.Nat.Nat
+ Data.Number.Nat: instance GHC.Enum.Enum Data.Number.Nat.Nat
+ Data.Number.Nat: instance GHC.Num.Num Data.Number.Nat.Nat
+ Data.Number.Nat: instance GHC.Read.Read Data.Number.Nat.Nat
+ Data.Number.Nat: instance GHC.Real.Integral Data.Number.Nat.Nat
+ Data.Number.Nat: instance GHC.Real.Real Data.Number.Nat.Nat
+ Data.Number.Nat: instance GHC.Show.Show Data.Number.Nat.Nat
+ Data.Number.Nat: newtype MaxNat
+ Data.Number.Nat: toNat :: Int -> Maybe Nat
+ Data.Number.Nat: unsafeNat :: Int -> Nat
+ Data.Number.Natural: MaxNatural :: Natural -> MaxNatural
+ Data.Number.Natural: [unMaxNatural] :: MaxNatural -> Natural
+ Data.Number.Natural: data Natural
+ Data.Number.Natural: fromNatural :: Natural -> Integer
+ Data.Number.Natural: fromNonNegativeRational :: NonNegativeRational -> Rational
+ Data.Number.Natural: instance GHC.Base.Monoid Data.Number.Natural.MaxNatural
+ Data.Number.Natural: instance GHC.Classes.Eq Data.Number.Natural.Natural
+ Data.Number.Natural: instance GHC.Classes.Ord Data.Number.Natural.Natural
+ Data.Number.Natural: instance GHC.Enum.Enum Data.Number.Natural.Natural
+ Data.Number.Natural: instance GHC.Num.Num Data.Number.Natural.Natural
+ Data.Number.Natural: instance GHC.Read.Read Data.Number.Natural.Natural
+ Data.Number.Natural: instance GHC.Real.Integral Data.Number.Natural.Natural
+ Data.Number.Natural: instance GHC.Real.Real Data.Number.Natural.Natural
+ Data.Number.Natural: instance GHC.Show.Show Data.Number.Natural.Natural
+ Data.Number.Natural: newtype MaxNatural
+ Data.Number.Natural: toNatural :: Integer -> Maybe Natural
+ Data.Number.Natural: toNonNegativeRational :: Rational -> Maybe NonNegativeRational
+ Data.Number.Natural: type NonNegativeRational = Ratio Natural
+ Data.Number.Natural: unsafeNatural :: Integer -> Natural
+ Data.Number.Natural: unsafeNonNegativeRational :: Rational -> NonNegativeRational
+ Language.Hakaru.CodeGen.AST: (.&&.) :: CExpr -> CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: (.*.) :: CExpr -> CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: (.*=.) :: CExpr -> CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: (.+.) :: CExpr -> CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: (.+=.) :: CExpr -> CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: (.-.) :: CExpr -> CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: (./.) :: CExpr -> CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: (.<.) :: CExpr -> CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: (.<=.) :: CExpr -> CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: (.=.) :: CExpr -> CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: (.==.) :: CExpr -> CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: (.>.) :: CExpr -> CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: (.>=.) :: CExpr -> CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: (.||.) :: CExpr -> CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: CAST :: [CExtDecl] -> CAST
+ Language.Hakaru.CodeGen.AST: CAddAssOp :: CAssignOp
+ Language.Hakaru.CodeGen.AST: CAddOp :: CBinaryOp
+ Language.Hakaru.CodeGen.AST: CAdrOp :: CUnaryOp
+ Language.Hakaru.CodeGen.AST: CAndAssOp :: CAssignOp
+ Language.Hakaru.CodeGen.AST: CAndOp :: CBinaryOp
+ Language.Hakaru.CodeGen.AST: CArrDesig :: CExpr -> CPartDesig
+ Language.Hakaru.CodeGen.AST: CAssign :: CAssignOp -> CExpr -> CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: CAssignOp :: CAssignOp
+ Language.Hakaru.CodeGen.AST: CAuto :: CStorageSpec
+ Language.Hakaru.CodeGen.AST: CBinary :: CBinaryOp -> CExpr -> CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: CBlockDecl :: CDecl -> CCompoundBlockItem
+ Language.Hakaru.CodeGen.AST: CBlockStat :: CStat -> CCompoundBlockItem
+ Language.Hakaru.CodeGen.AST: CBreak :: CStat
+ Language.Hakaru.CodeGen.AST: CCall :: CExpr -> [CExpr] -> CExpr
+ Language.Hakaru.CodeGen.AST: CCase :: CExpr -> CStat -> CStat
+ Language.Hakaru.CodeGen.AST: CCast :: CDecl -> CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: CChar :: CTypeSpec
+ Language.Hakaru.CodeGen.AST: CCharConst :: Char -> CConst
+ Language.Hakaru.CodeGen.AST: CComma :: [CExpr] -> CExpr
+ Language.Hakaru.CodeGen.AST: CComment :: String -> CStat
+ Language.Hakaru.CodeGen.AST: CCommentExt :: String -> CExtDecl
+ Language.Hakaru.CodeGen.AST: CCompOp :: CUnaryOp
+ Language.Hakaru.CodeGen.AST: CCompound :: [CCompoundBlockItem] -> CStat
+ Language.Hakaru.CodeGen.AST: CCompoundLit :: CDecl -> CInit -> CExpr
+ Language.Hakaru.CodeGen.AST: CCond :: CExpr -> CExpr -> CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: CConstQual :: CTypeQual
+ Language.Hakaru.CodeGen.AST: CConstant :: CConst -> CExpr
+ Language.Hakaru.CodeGen.AST: CCont :: CStat
+ Language.Hakaru.CodeGen.AST: CDDeclrArr :: CDirectDeclr -> CExpr -> CDirectDeclr
+ Language.Hakaru.CodeGen.AST: CDDeclrFun :: CDirectDeclr -> [CTypeSpec] -> CDirectDeclr
+ Language.Hakaru.CodeGen.AST: CDDeclrIdent :: Ident -> CDirectDeclr
+ Language.Hakaru.CodeGen.AST: CDecl :: [CDeclSpec] -> [(CDeclr, Maybe CInit)] -> CDecl
+ Language.Hakaru.CodeGen.AST: CDeclExt :: CDecl -> CExtDecl
+ Language.Hakaru.CodeGen.AST: CDeclr :: (Maybe CPtrDeclr) -> [CDirectDeclr] -> CDeclr
+ Language.Hakaru.CodeGen.AST: CDefault :: CStat -> CStat
+ Language.Hakaru.CodeGen.AST: CDivAssOp :: CAssignOp
+ Language.Hakaru.CodeGen.AST: CDivOp :: CBinaryOp
+ Language.Hakaru.CodeGen.AST: CDouble :: CTypeSpec
+ Language.Hakaru.CodeGen.AST: CEnum :: (Maybe Ident) -> [(Ident, Maybe CExpr)] -> CEnum
+ Language.Hakaru.CodeGen.AST: CEnumType :: CEnum -> CTypeSpec
+ Language.Hakaru.CodeGen.AST: CEqOp :: CBinaryOp
+ Language.Hakaru.CodeGen.AST: CExpr :: (Maybe CExpr) -> CStat
+ Language.Hakaru.CodeGen.AST: CExtern :: CStorageSpec
+ Language.Hakaru.CodeGen.AST: CFloat :: CTypeSpec
+ Language.Hakaru.CodeGen.AST: CFloatConst :: Float -> CConst
+ Language.Hakaru.CodeGen.AST: CFor :: (Maybe CExpr) -> (Maybe CExpr) -> (Maybe CExpr) -> CStat -> CStat
+ Language.Hakaru.CodeGen.AST: CFunDef :: [CDeclSpec] -> CDeclr -> [CDecl] -> CStat -> CFunDef
+ Language.Hakaru.CodeGen.AST: CFunDefExt :: CFunDef -> CExtDecl
+ Language.Hakaru.CodeGen.AST: CFunSpec :: CFunSpec -> CDeclSpec
+ Language.Hakaru.CodeGen.AST: CGeqOp :: CBinaryOp
+ Language.Hakaru.CodeGen.AST: CGoto :: Ident -> CStat
+ Language.Hakaru.CodeGen.AST: CGrOp :: CBinaryOp
+ Language.Hakaru.CodeGen.AST: CIf :: CExpr -> CStat -> (Maybe CStat) -> CStat
+ Language.Hakaru.CodeGen.AST: CIndOp :: CUnaryOp
+ Language.Hakaru.CodeGen.AST: CIndex :: CExpr -> CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: CInitExpr :: CExpr -> CInit
+ Language.Hakaru.CodeGen.AST: CInitList :: [([CPartDesig], CInit)] -> CInit
+ Language.Hakaru.CodeGen.AST: CInt :: CTypeSpec
+ Language.Hakaru.CodeGen.AST: CIntConst :: Integer -> CConst
+ Language.Hakaru.CodeGen.AST: CLabel :: Ident -> CStat -> CStat
+ Language.Hakaru.CodeGen.AST: CLeOp :: CBinaryOp
+ Language.Hakaru.CodeGen.AST: CLeqOp :: CBinaryOp
+ Language.Hakaru.CodeGen.AST: CLndOp :: CBinaryOp
+ Language.Hakaru.CodeGen.AST: CLong :: CTypeSpec
+ Language.Hakaru.CodeGen.AST: CLorOp :: CBinaryOp
+ Language.Hakaru.CodeGen.AST: CMember :: CExpr -> Ident -> Bool -> CExpr
+ Language.Hakaru.CodeGen.AST: CMemberDesig :: CExpr -> CPartDesig
+ Language.Hakaru.CodeGen.AST: CMinOp :: CUnaryOp
+ Language.Hakaru.CodeGen.AST: CMulAssOp :: CAssignOp
+ Language.Hakaru.CodeGen.AST: CMulOp :: CBinaryOp
+ Language.Hakaru.CodeGen.AST: CNegOp :: CUnaryOp
+ Language.Hakaru.CodeGen.AST: CNeqOp :: CBinaryOp
+ Language.Hakaru.CodeGen.AST: COrAssOp :: CAssignOp
+ Language.Hakaru.CodeGen.AST: COrOp :: CBinaryOp
+ Language.Hakaru.CodeGen.AST: CPPExt :: Preprocessor -> CExtDecl
+ Language.Hakaru.CodeGen.AST: CPPStat :: Preprocessor -> CStat
+ Language.Hakaru.CodeGen.AST: CPlusOp :: CUnaryOp
+ Language.Hakaru.CodeGen.AST: CPostDecOp :: CUnaryOp
+ Language.Hakaru.CodeGen.AST: CPostIncOp :: CUnaryOp
+ Language.Hakaru.CodeGen.AST: CPreDecOp :: CUnaryOp
+ Language.Hakaru.CodeGen.AST: CPreIncOp :: CUnaryOp
+ Language.Hakaru.CodeGen.AST: CPtrDeclr :: [CTypeQual] -> CPtrDeclr
+ Language.Hakaru.CodeGen.AST: CRegister :: CStorageSpec
+ Language.Hakaru.CodeGen.AST: CReturn :: (Maybe CExpr) -> CStat
+ Language.Hakaru.CodeGen.AST: CRmdAssOp :: CAssignOp
+ Language.Hakaru.CodeGen.AST: CRmdOp :: CBinaryOp
+ Language.Hakaru.CodeGen.AST: CSUSpec :: CSUTag -> (Maybe Ident) -> [CDecl] -> CSUSpec
+ Language.Hakaru.CodeGen.AST: CSUType :: CSUSpec -> CTypeSpec
+ Language.Hakaru.CodeGen.AST: CShlAssOp :: CAssignOp
+ Language.Hakaru.CodeGen.AST: CShlOp :: CBinaryOp
+ Language.Hakaru.CodeGen.AST: CShort :: CTypeSpec
+ Language.Hakaru.CodeGen.AST: CShrAssOp :: CAssignOp
+ Language.Hakaru.CodeGen.AST: CShrOp :: CBinaryOp
+ Language.Hakaru.CodeGen.AST: CSigned :: CTypeSpec
+ Language.Hakaru.CodeGen.AST: CSizeOfExpr :: CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: CSizeOfType :: CDecl -> CExpr
+ Language.Hakaru.CodeGen.AST: CStatic :: CStorageSpec
+ Language.Hakaru.CodeGen.AST: CStorageSpec :: CStorageSpec -> CDeclSpec
+ Language.Hakaru.CodeGen.AST: CStringConst :: String -> CConst
+ Language.Hakaru.CodeGen.AST: CStructTag :: CSUTag
+ Language.Hakaru.CodeGen.AST: CSubAssOp :: CAssignOp
+ Language.Hakaru.CodeGen.AST: CSubOp :: CBinaryOp
+ Language.Hakaru.CodeGen.AST: CSwitch :: CExpr -> CStat -> CStat
+ Language.Hakaru.CodeGen.AST: CTypeDef :: CStorageSpec
+ Language.Hakaru.CodeGen.AST: CTypeDefType :: Ident -> CTypeSpec
+ Language.Hakaru.CodeGen.AST: CTypeQual :: CTypeQual -> CDeclSpec
+ Language.Hakaru.CodeGen.AST: CTypeSpec :: CTypeSpec -> CDeclSpec
+ Language.Hakaru.CodeGen.AST: CUnary :: CUnaryOp -> CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: CUnionTag :: CSUTag
+ Language.Hakaru.CodeGen.AST: CUnsigned :: CTypeSpec
+ Language.Hakaru.CodeGen.AST: CVar :: Ident -> CExpr
+ Language.Hakaru.CodeGen.AST: CVoid :: CTypeSpec
+ Language.Hakaru.CodeGen.AST: CVolatQual :: CTypeQual
+ Language.Hakaru.CodeGen.AST: CWhile :: CExpr -> CStat -> Bool -> CStat
+ Language.Hakaru.CodeGen.AST: CXorAssOp :: CAssignOp
+ Language.Hakaru.CodeGen.AST: CXorOp :: CBinaryOp
+ Language.Hakaru.CodeGen.AST: Ident :: String -> Ident
+ Language.Hakaru.CodeGen.AST: Inline :: CFunSpec
+ Language.Hakaru.CodeGen.AST: PPDefine :: String -> String -> Preprocessor
+ Language.Hakaru.CodeGen.AST: PPElif :: String -> Preprocessor
+ Language.Hakaru.CodeGen.AST: PPElse :: String -> Preprocessor
+ Language.Hakaru.CodeGen.AST: PPEndif :: String -> Preprocessor
+ Language.Hakaru.CodeGen.AST: PPError :: String -> Preprocessor
+ Language.Hakaru.CodeGen.AST: PPIf :: String -> Preprocessor
+ Language.Hakaru.CodeGen.AST: PPIfDef :: String -> Preprocessor
+ Language.Hakaru.CodeGen.AST: PPIfNDef :: String -> Preprocessor
+ Language.Hakaru.CodeGen.AST: PPInclude :: String -> Preprocessor
+ Language.Hakaru.CodeGen.AST: PPPragma :: [String] -> Preprocessor
+ Language.Hakaru.CodeGen.AST: PPUndef :: String -> Preprocessor
+ Language.Hakaru.CodeGen.AST: address :: CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: data CAST
+ Language.Hakaru.CodeGen.AST: data CAssignOp
+ Language.Hakaru.CodeGen.AST: data CBinaryOp
+ Language.Hakaru.CodeGen.AST: data CCompoundBlockItem
+ Language.Hakaru.CodeGen.AST: data CConst
+ Language.Hakaru.CodeGen.AST: data CDecl
+ Language.Hakaru.CodeGen.AST: data CDeclSpec
+ Language.Hakaru.CodeGen.AST: data CDeclr
+ Language.Hakaru.CodeGen.AST: data CDirectDeclr
+ Language.Hakaru.CodeGen.AST: data CEnum
+ Language.Hakaru.CodeGen.AST: data CExpr
+ Language.Hakaru.CodeGen.AST: data CExtDecl
+ Language.Hakaru.CodeGen.AST: data CFunDef
+ Language.Hakaru.CodeGen.AST: data CFunSpec
+ Language.Hakaru.CodeGen.AST: data CInit
+ Language.Hakaru.CodeGen.AST: data CPartDesig
+ Language.Hakaru.CodeGen.AST: data CPtrDeclr
+ Language.Hakaru.CodeGen.AST: data CSUSpec
+ Language.Hakaru.CodeGen.AST: data CSUTag
+ Language.Hakaru.CodeGen.AST: data CStat
+ Language.Hakaru.CodeGen.AST: data CStorageSpec
+ Language.Hakaru.CodeGen.AST: data CTypeQual
+ Language.Hakaru.CodeGen.AST: data CTypeSpec
+ Language.Hakaru.CodeGen.AST: data CUnaryOp
+ Language.Hakaru.CodeGen.AST: data Ident
+ Language.Hakaru.CodeGen.AST: data Preprocessor
+ Language.Hakaru.CodeGen.AST: exp :: CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: expm1 :: CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: floatE :: Float -> CExpr
+ Language.Hakaru.CodeGen.AST: indirect :: CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: infinityE :: CExpr
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.CAST
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.CAssignOp
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.CBinaryOp
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.CCompoundBlockItem
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.CConst
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.CDecl
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.CDeclSpec
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.CDeclr
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.CDirectDeclr
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.CEnum
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.CExpr
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.CExtDecl
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.CFunDef
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.CFunSpec
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.CInit
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.CPartDesig
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.CPtrDeclr
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.CSUSpec
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.CSUTag
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.CStat
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.CStorageSpec
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.CTypeQual
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.CTypeSpec
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.CUnaryOp
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.Ident
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Eq Language.Hakaru.CodeGen.AST.Preprocessor
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.CAST
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.CAssignOp
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.CBinaryOp
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.CCompoundBlockItem
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.CConst
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.CDecl
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.CDeclSpec
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.CDeclr
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.CDirectDeclr
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.CEnum
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.CExpr
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.CExtDecl
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.CFunDef
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.CFunSpec
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.CInit
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.CPartDesig
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.CPtrDeclr
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.CSUSpec
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.CSUTag
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.CStat
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.CStorageSpec
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.CTypeQual
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.CTypeSpec
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.CUnaryOp
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.Ident
+ Language.Hakaru.CodeGen.AST: instance GHC.Classes.Ord Language.Hakaru.CodeGen.AST.Preprocessor
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.CAST
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.CAssignOp
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.CBinaryOp
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.CCompoundBlockItem
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.CConst
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.CDecl
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.CDeclSpec
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.CDeclr
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.CDirectDeclr
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.CEnum
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.CExpr
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.CExtDecl
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.CFunDef
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.CFunSpec
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.CInit
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.CPartDesig
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.CPtrDeclr
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.CSUSpec
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.CSUTag
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.CStat
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.CStorageSpec
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.CTypeQual
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.CTypeSpec
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.CUnaryOp
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.Ident
+ Language.Hakaru.CodeGen.AST: instance GHC.Show.Show Language.Hakaru.CodeGen.AST.Preprocessor
+ Language.Hakaru.CodeGen.AST: intE :: Integer -> CExpr
+ Language.Hakaru.CodeGen.AST: log :: CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: log1p :: CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: mkUnary :: String -> CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: negInfinityE :: CExpr
+ Language.Hakaru.CodeGen.AST: printfE :: [CExpr] -> CExpr
+ Language.Hakaru.CodeGen.AST: rand :: CExpr
+ Language.Hakaru.CodeGen.AST: seqCStat :: [CStat] -> CStat
+ Language.Hakaru.CodeGen.AST: sqrt :: CExpr -> CExpr
+ Language.Hakaru.CodeGen.AST: stringE :: String -> CExpr
+ Language.Hakaru.CodeGen.CodeGenMonad: CG :: [String] -> Set String -> [CExtDecl] -> [CDecl] -> [CStat] -> Env -> Bool -> CG
+ Language.Hakaru.CodeGen.CodeGenMonad: [declarations] :: CG -> [CDecl]
+ Language.Hakaru.CodeGen.CodeGenMonad: [extDecls] :: CG -> [CExtDecl]
+ Language.Hakaru.CodeGen.CodeGenMonad: [freshNames] :: CG -> [String]
+ Language.Hakaru.CodeGen.CodeGenMonad: [parallel] :: CG -> Bool
+ Language.Hakaru.CodeGen.CodeGenMonad: [reservedNames] :: CG -> Set String
+ Language.Hakaru.CodeGen.CodeGenMonad: [statements] :: CG -> [CStat]
+ Language.Hakaru.CodeGen.CodeGenMonad: [varEnv] :: CG -> Env
+ Language.Hakaru.CodeGen.CodeGenMonad: assign :: Ident -> CExpr -> CodeGen ()
+ Language.Hakaru.CodeGen.CodeGenMonad: createIdent :: Variable (a :: Hakaru) -> CodeGen Ident
+ Language.Hakaru.CodeGen.CodeGenMonad: data CG
+ Language.Hakaru.CodeGen.CodeGenMonad: declare :: Sing (a :: Hakaru) -> Ident -> CodeGen ()
+ Language.Hakaru.CodeGen.CodeGenMonad: declare' :: CDecl -> CodeGen ()
+ Language.Hakaru.CodeGen.CodeGenMonad: defineFunction :: Sing (a :: Hakaru) -> Ident -> [CDecl] -> CodeGen () -> CodeGen ()
+ Language.Hakaru.CodeGen.CodeGenMonad: doWhileCG :: CExpr -> CodeGen () -> CodeGen ()
+ Language.Hakaru.CodeGen.CodeGenMonad: emptyCG :: CG
+ Language.Hakaru.CodeGen.CodeGenMonad: extDeclare :: CExtDecl -> CodeGen ()
+ Language.Hakaru.CodeGen.CodeGenMonad: forCG :: CExpr -> CExpr -> CExpr -> CodeGen () -> CodeGen ()
+ Language.Hakaru.CodeGen.CodeGenMonad: funCG :: CTypeSpec -> Ident -> [CDecl] -> CodeGen () -> CodeGen ()
+ Language.Hakaru.CodeGen.CodeGenMonad: genIdent :: CodeGen Ident
+ Language.Hakaru.CodeGen.CodeGenMonad: genIdent' :: String -> CodeGen Ident
+ Language.Hakaru.CodeGen.CodeGenMonad: instance GHC.Show.Show Language.Hakaru.CodeGen.CodeGenMonad.Env
+ Language.Hakaru.CodeGen.CodeGenMonad: isParallel :: CodeGen Bool
+ Language.Hakaru.CodeGen.CodeGenMonad: lookupIdent :: Variable (a :: Hakaru) -> CodeGen Ident
+ Language.Hakaru.CodeGen.CodeGenMonad: mkParallel :: CodeGen ()
+ Language.Hakaru.CodeGen.CodeGenMonad: mkSequential :: CodeGen ()
+ Language.Hakaru.CodeGen.CodeGenMonad: putExprStat :: CExpr -> CodeGen ()
+ Language.Hakaru.CodeGen.CodeGenMonad: putStat :: CStat -> CodeGen ()
+ Language.Hakaru.CodeGen.CodeGenMonad: reductionCG :: CBinaryOp -> Ident -> CExpr -> CExpr -> CExpr -> CodeGen () -> CodeGen ()
+ Language.Hakaru.CodeGen.CodeGenMonad: reserveName :: String -> CodeGen ()
+ Language.Hakaru.CodeGen.CodeGenMonad: runCodeGen :: CodeGen a -> ([CExtDecl], [CDecl], [CStat])
+ Language.Hakaru.CodeGen.CodeGenMonad: runCodeGenBlock :: CodeGen a -> CodeGen CStat
+ Language.Hakaru.CodeGen.CodeGenMonad: runCodeGenWith :: CodeGen a -> CG -> [CExtDecl]
+ Language.Hakaru.CodeGen.CodeGenMonad: suffixes :: [String]
+ Language.Hakaru.CodeGen.CodeGenMonad: type CodeGen = State CG
+ Language.Hakaru.CodeGen.CodeGenMonad: whileCG :: CExpr -> CodeGen () -> CodeGen ()
+ Language.Hakaru.CodeGen.Flatten: flattenABT :: ABT Term abt => abt '[] a -> (CExpr -> CodeGen ())
+ Language.Hakaru.CodeGen.Flatten: flattenTerm :: ABT Term abt => Term abt a -> (CExpr -> CodeGen ())
+ Language.Hakaru.CodeGen.Flatten: flattenVar :: Variable (a :: Hakaru) -> (CExpr -> CodeGen ())
+ Language.Hakaru.CodeGen.Pretty: class Pretty a where pretty = prettyPrec 0 prettyPrec _ = pretty
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.CAST
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.CAssignOp
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.CBinaryOp
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.CCompoundBlockItem
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.CConst
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.CDecl
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.CDeclSpec
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.CDeclr
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.CDirectDeclr
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.CEnum
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.CExpr
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.CExtDecl
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.CFunDef
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.CInit
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.CPartDesig
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.CPtrDeclr
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.CSUSpec
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.CSUTag
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.CStat
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.CStorageSpec
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.CTypeQual
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.CTypeSpec
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.CUnaryOp
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.Ident
+ Language.Hakaru.CodeGen.Pretty: instance Language.Hakaru.CodeGen.Pretty.Pretty Language.Hakaru.CodeGen.AST.Preprocessor
+ Language.Hakaru.CodeGen.Pretty: pretty :: Pretty a => a -> Doc
+ Language.Hakaru.CodeGen.Pretty: prettyPrint :: Pretty a => a -> String
+ Language.Hakaru.CodeGen.Types: arrayData :: CExpr -> CExpr
+ Language.Hakaru.CodeGen.Types: arrayDeclaration :: Sing (a :: Hakaru) -> Ident -> CDecl
+ Language.Hakaru.CodeGen.Types: arrayName :: Sing (a :: Hakaru) -> String
+ Language.Hakaru.CodeGen.Types: arrayPtrData :: CExpr -> CExpr
+ Language.Hakaru.CodeGen.Types: arrayPtrSize :: CExpr -> CExpr
+ Language.Hakaru.CodeGen.Types: arraySize :: CExpr -> CExpr
+ Language.Hakaru.CodeGen.Types: arrayStruct :: Sing (a :: Hakaru) -> CExtDecl
+ Language.Hakaru.CodeGen.Types: binaryOp :: NaryOp a -> CExpr -> CExpr -> CExpr
+ Language.Hakaru.CodeGen.Types: boolTyp :: CDecl
+ Language.Hakaru.CodeGen.Types: buildDeclaration :: CTypeSpec -> Ident -> CDecl
+ Language.Hakaru.CodeGen.Types: buildPtrDeclaration :: CTypeSpec -> Ident -> CDecl
+ Language.Hakaru.CodeGen.Types: buildStruct :: Maybe Ident -> [CDecl] -> CTypeSpec
+ Language.Hakaru.CodeGen.Types: buildType :: Sing (a :: Hakaru) -> [CTypeSpec]
+ Language.Hakaru.CodeGen.Types: buildUnion :: [CDecl] -> CTypeSpec
+ Language.Hakaru.CodeGen.Types: datumDeclaration :: (Sing (HData' t)) -> Ident -> CDecl
+ Language.Hakaru.CodeGen.Types: datumName :: Sing (a :: [[HakaruFun]]) -> String
+ Language.Hakaru.CodeGen.Types: datumProd :: Sing (a :: [HakaruFun]) -> Ident -> Maybe CDecl
+ Language.Hakaru.CodeGen.Types: datumStruct :: (Sing (HData' t)) -> CExtDecl
+ Language.Hakaru.CodeGen.Types: datumSum :: Sing (a :: [[HakaruFun]]) -> Ident -> CDecl
+ Language.Hakaru.CodeGen.Types: doubleDecl :: CDecl
+ Language.Hakaru.CodeGen.Types: doublePtr :: CDecl
+ Language.Hakaru.CodeGen.Types: functionDef :: Sing (a :: Hakaru) -> Ident -> [CDecl] -> [CDecl] -> [CStat] -> CFunDef
+ Language.Hakaru.CodeGen.Types: intDecl :: CDecl
+ Language.Hakaru.CodeGen.Types: intPtr :: CDecl
+ Language.Hakaru.CodeGen.Types: mdataDeclaration :: Sing (a :: Hakaru) -> Ident -> CDecl
+ Language.Hakaru.CodeGen.Types: mdataName :: Sing (a :: Hakaru) -> String
+ Language.Hakaru.CodeGen.Types: mdataPtrDeclaration :: Sing (a :: Hakaru) -> Ident -> CDecl
+ Language.Hakaru.CodeGen.Types: mdataPtrSample :: CExpr -> CExpr
+ Language.Hakaru.CodeGen.Types: mdataPtrWeight :: CExpr -> CExpr
+ Language.Hakaru.CodeGen.Types: mdataSample :: CExpr -> CExpr
+ Language.Hakaru.CodeGen.Types: mdataStruct :: Sing (a :: Hakaru) -> CExtDecl
+ Language.Hakaru.CodeGen.Types: mdataStruct' :: Sing (a :: Hakaru) -> CTypeSpec
+ Language.Hakaru.CodeGen.Types: mdataWeight :: CExpr -> CExpr
+ Language.Hakaru.CodeGen.Types: mkDecl :: [CTypeSpec] -> CDecl
+ Language.Hakaru.CodeGen.Types: mkPtrDecl :: [CTypeSpec] -> CDecl
+ Language.Hakaru.CodeGen.Types: natDecl :: CDecl
+ Language.Hakaru.CodeGen.Types: natPtr :: CDecl
+ Language.Hakaru.CodeGen.Types: typeDeclaration :: Sing (a :: Hakaru) -> Ident -> CDecl
+ Language.Hakaru.CodeGen.Types: typePtrDeclaration :: Sing (a :: Hakaru) -> Ident -> CDecl
+ Language.Hakaru.CodeGen.Wrapper: PrintConfig :: Bool -> Bool -> PrintConfig
+ Language.Hakaru.CodeGen.Wrapper: [showProbInLog] :: PrintConfig -> Bool
+ Language.Hakaru.CodeGen.Wrapper: [showWeights] :: PrintConfig -> Bool
+ Language.Hakaru.CodeGen.Wrapper: data PrintConfig
+ Language.Hakaru.CodeGen.Wrapper: instance GHC.Show.Show Language.Hakaru.CodeGen.Wrapper.PrintConfig
+ Language.Hakaru.CodeGen.Wrapper: wrapProgram :: TypedAST (TrivialABT Term) -> Maybe String -> PrintConfig -> CodeGen ()
+ Language.Hakaru.Command: parseAndInfer :: Text -> Either Text (TypedAST (TrivialABT Term))
+ Language.Hakaru.Command: readFromFile :: String -> IO Text
+ Language.Hakaru.Command: splitLines :: Text -> Maybe (Vector Text)
+ Language.Hakaru.Command: type Term a = TrivialABT Term '[] a
+ Language.Hakaru.Command: writeToFile :: String -> (Text -> IO ())
+ Language.Hakaru.Disintegrate: atomize :: (ABT Term abt) => TermEvaluator abt (Dis abt)
+ Language.Hakaru.Disintegrate: constrainOutcome :: forall abt a. (ABT Term abt) => abt '[] a -> abt '[] (HMeasure a) -> Dis abt ()
+ Language.Hakaru.Disintegrate: constrainValue :: (ABT Term abt) => abt '[] a -> abt '[] a -> Dis abt ()
+ Language.Hakaru.Disintegrate: density :: (ABT Term abt) => abt '[] (HMeasure a) -> [abt '[] (a :-> HProb)]
+ Language.Hakaru.Disintegrate: densityWithVar :: (ABT Term abt) => Text -> Sing a -> abt '[] (HMeasure a) -> [abt '[] (a :-> HProb)]
+ Language.Hakaru.Disintegrate: determine :: (ABT Term abt) => [abt '[] a] -> Maybe (abt '[] a)
+ Language.Hakaru.Disintegrate: disintegrate :: (ABT Term abt) => abt '[] (HMeasure (HPair a b)) -> [abt '[] (a :-> HMeasure b)]
+ Language.Hakaru.Disintegrate: disintegrateWithVar :: (ABT Term abt) => Text -> Sing a -> abt '[] (HMeasure (HPair a b)) -> [abt '[] (a :-> HMeasure b)]
+ Language.Hakaru.Disintegrate: observe :: (ABT Term abt) => abt '[] (HMeasure a) -> abt '[] a -> [abt '[] (HMeasure a)]
+ Language.Hakaru.Disintegrate: perform :: forall abt. (ABT Term abt) => MeasureEvaluator abt (Dis abt)
+ Language.Hakaru.Evaluation.Coalesce: coalesce :: AST -> AST
+ Language.Hakaru.Evaluation.ConstantPropagation: constantPropagation :: forall abt a. (ABT Term abt) => abt '[] a -> abt '[] a
+ Language.Hakaru.Evaluation.DisintegrationMonad: Dis :: (forall a. [Index (abt '[])] -> (x -> Ans abt a) -> Ans abt a) -> Dis abt x
+ Language.Hakaru.Evaluation.DisintegrationMonad: ListContext :: {-# UNPACK #-} !Nat -> [Statement abt p] -> ListContext
+ Language.Hakaru.Evaluation.DisintegrationMonad: [Loc] :: Variable a -> [Variable HNat] -> Loc ast a
+ Language.Hakaru.Evaluation.DisintegrationMonad: [MultiLoc] :: Variable a -> [Variable HNat] -> Loc ast (HArray a)
+ Language.Hakaru.Evaluation.DisintegrationMonad: [nextFreshNat] :: ListContext -> {-# UNPACK #-} !Nat
+ Language.Hakaru.Evaluation.DisintegrationMonad: [statements] :: ListContext -> [Statement abt p]
+ Language.Hakaru.Evaluation.DisintegrationMonad: [unDis] :: Dis abt x -> forall a. [Index (abt '[])] -> (x -> Ans abt a) -> Ans abt a
+ Language.Hakaru.Evaluation.DisintegrationMonad: adjustLoc :: (ABT Term abt) => Variable (a :: Hakaru) -> (Assoc (Loc (abt '[])) -> Assoc (Loc (abt '[]))) -> Dis abt ()
+ Language.Hakaru.Evaluation.DisintegrationMonad: apply :: (ABT Term abt) => [(Index (abt '[]), Index (abt '[]))] -> abt '[] a -> Dis abt (abt '[] a)
+ Language.Hakaru.Evaluation.DisintegrationMonad: bot :: (ABT Term abt) => Dis abt a
+ Language.Hakaru.Evaluation.DisintegrationMonad: choose :: (ABT Term abt) => [Dis abt a] -> Dis abt a
+ Language.Hakaru.Evaluation.DisintegrationMonad: data ListContext (abt :: [Hakaru] -> Hakaru -> *) (p :: Purity)
+ Language.Hakaru.Evaluation.DisintegrationMonad: data Loc :: (Hakaru -> *) -> Hakaru -> *
+ Language.Hakaru.Evaluation.DisintegrationMonad: emit :: (ABT Term abt) => Text -> Sing a -> (forall r. abt '[a] (HMeasure r) -> abt '[] (HMeasure r)) -> Dis abt (Variable a)
+ Language.Hakaru.Evaluation.DisintegrationMonad: emitFork_ :: (ABT Term abt, Traversable t) => (forall r. t (abt '[] (HMeasure r)) -> abt '[] (HMeasure r)) -> t (Dis abt a) -> Dis abt a
+ Language.Hakaru.Evaluation.DisintegrationMonad: emitGuard :: (ABT Term abt) => abt '[] HBool -> Dis abt ()
+ Language.Hakaru.Evaluation.DisintegrationMonad: emitLet :: (ABT Term abt) => abt '[] a -> Dis abt (Variable a)
+ Language.Hakaru.Evaluation.DisintegrationMonad: emitLet' :: (ABT Term abt) => abt '[] a -> Dis abt (abt '[] a)
+ Language.Hakaru.Evaluation.DisintegrationMonad: emitMBind :: (ABT Term abt) => abt '[] (HMeasure a) -> Dis abt (Variable a)
+ Language.Hakaru.Evaluation.DisintegrationMonad: emitMBind_ :: (ABT Term abt) => abt '[] (HMeasure HUnit) -> Dis abt ()
+ Language.Hakaru.Evaluation.DisintegrationMonad: emitSuperpose :: (ABT Term abt) => [abt '[] (HMeasure a)] -> Dis abt (Variable a)
+ Language.Hakaru.Evaluation.DisintegrationMonad: emitUnpair :: (ABT Term abt) => Whnf abt (HPair a b) -> Dis abt (abt '[] a, abt '[] b)
+ Language.Hakaru.Evaluation.DisintegrationMonad: emitWeight :: (ABT Term abt) => abt '[] HProb -> Dis abt ()
+ Language.Hakaru.Evaluation.DisintegrationMonad: emit_ :: (ABT Term abt) => (forall r. abt '[] (HMeasure r) -> abt '[] (HMeasure r)) -> Dis abt ()
+ Language.Hakaru.Evaluation.DisintegrationMonad: extendIndices :: (ABT Term abt) => Index (abt '[]) -> [Index (abt '[])] -> [Index (abt '[])]
+ Language.Hakaru.Evaluation.DisintegrationMonad: extendLocInds :: Variable HNat -> [Variable HNat] -> [Variable HNat]
+ Language.Hakaru.Evaluation.DisintegrationMonad: freeLocError :: Variable (a :: Hakaru) -> b
+ Language.Hakaru.Evaluation.DisintegrationMonad: getIndices :: EvaluationMonad abt m p => m [Index (abt '[])]
+ Language.Hakaru.Evaluation.DisintegrationMonad: getLocs :: (ABT Term abt) => Dis abt (Assocs (Loc (abt '[])))
+ Language.Hakaru.Evaluation.DisintegrationMonad: getStatements :: Dis abt [Statement abt Impure]
+ Language.Hakaru.Evaluation.DisintegrationMonad: insertLoc :: (ABT Term abt) => Variable a -> Loc (abt '[]) a -> Dis abt ()
+ Language.Hakaru.Evaluation.DisintegrationMonad: instance GHC.Base.Alternative (Language.Hakaru.Evaluation.DisintegrationMonad.Dis abt)
+ Language.Hakaru.Evaluation.DisintegrationMonad: instance GHC.Base.Applicative (Language.Hakaru.Evaluation.DisintegrationMonad.Dis abt)
+ Language.Hakaru.Evaluation.DisintegrationMonad: instance GHC.Base.Functor (Language.Hakaru.Evaluation.DisintegrationMonad.Dis abt)
+ Language.Hakaru.Evaluation.DisintegrationMonad: instance GHC.Base.Monad (Language.Hakaru.Evaluation.DisintegrationMonad.Dis abt)
+ Language.Hakaru.Evaluation.DisintegrationMonad: instance GHC.Base.MonadPlus (Language.Hakaru.Evaluation.DisintegrationMonad.Dis abt)
+ Language.Hakaru.Evaluation.DisintegrationMonad: instance Language.Hakaru.Syntax.ABT.ABT Language.Hakaru.Syntax.AST.Term abt => Language.Hakaru.Evaluation.Types.EvaluationMonad abt (Language.Hakaru.Evaluation.DisintegrationMonad.Dis abt) 'Language.Hakaru.Evaluation.Types.Impure
+ Language.Hakaru.Evaluation.DisintegrationMonad: mkLoc :: (ABT Term abt) => Text -> Variable (a :: Hakaru) -> [Variable HNat] -> Dis abt (Variable a)
+ Language.Hakaru.Evaluation.DisintegrationMonad: newtype Dis abt x
+ Language.Hakaru.Evaluation.DisintegrationMonad: pushPlate :: (ABT Term abt) => abt '[] HNat -> abt '[HNat] (HMeasure a) -> Dis abt (Variable (HArray a))
+ Language.Hakaru.Evaluation.DisintegrationMonad: putLocs :: (ABT Term abt) => Assocs (Loc (abt '[])) -> Dis abt ()
+ Language.Hakaru.Evaluation.DisintegrationMonad: putStatements :: [Statement abt Impure] -> Dis abt ()
+ Language.Hakaru.Evaluation.DisintegrationMonad: runDis :: (ABT Term abt, Foldable f) => Dis abt (abt '[] a) -> f (Some2 abt) -> [abt '[] (HMeasure a)]
+ Language.Hakaru.Evaluation.DisintegrationMonad: sizeInnermostInd :: (ABT Term abt) => Variable (a :: Hakaru) -> Dis abt (abt '[] HNat)
+ Language.Hakaru.Evaluation.DisintegrationMonad: statementInds :: Statement abt p -> [Index (abt '[])]
+ Language.Hakaru.Evaluation.DisintegrationMonad: type Ans abt a = ListContext abt Impure -> Assocs (Loc (abt '[])) -> [abt '[] (HMeasure a)]
+ Language.Hakaru.Evaluation.DisintegrationMonad: withIndices :: [Index (abt '[])] -> Dis abt a -> Dis abt a
+ Language.Hakaru.Evaluation.EvalMonad: Eval :: (forall a. (x -> PureAns abt a) -> PureAns abt a) -> Eval abt x
+ Language.Hakaru.Evaluation.EvalMonad: ListContext :: {-# UNPACK #-} !Nat -> [Statement abt p] -> ListContext
+ Language.Hakaru.Evaluation.EvalMonad: [nextFreshNat] :: ListContext -> {-# UNPACK #-} !Nat
+ Language.Hakaru.Evaluation.EvalMonad: [statements] :: ListContext -> [Statement abt p]
+ Language.Hakaru.Evaluation.EvalMonad: [unEval] :: Eval abt x -> forall a. (x -> PureAns abt a) -> PureAns abt a
+ Language.Hakaru.Evaluation.EvalMonad: data ListContext (abt :: [Hakaru] -> Hakaru -> *) (p :: Purity)
+ Language.Hakaru.Evaluation.EvalMonad: instance GHC.Base.Applicative (Language.Hakaru.Evaluation.EvalMonad.Eval abt)
+ Language.Hakaru.Evaluation.EvalMonad: instance GHC.Base.Functor (Language.Hakaru.Evaluation.EvalMonad.Eval abt)
+ Language.Hakaru.Evaluation.EvalMonad: instance GHC.Base.Monad (Language.Hakaru.Evaluation.EvalMonad.Eval abt)
+ Language.Hakaru.Evaluation.EvalMonad: instance Language.Hakaru.Syntax.ABT.ABT Language.Hakaru.Syntax.AST.Term abt => Language.Hakaru.Evaluation.Types.EvaluationMonad abt (Language.Hakaru.Evaluation.EvalMonad.Eval abt) 'Language.Hakaru.Evaluation.Types.Pure
+ Language.Hakaru.Evaluation.EvalMonad: newtype Eval abt x
+ Language.Hakaru.Evaluation.EvalMonad: pureEvaluate :: (ABT Term abt) => TermEvaluator abt (Eval abt)
+ Language.Hakaru.Evaluation.EvalMonad: residualizePureListContext :: forall abt a. (ABT Term abt) => abt '[] a -> ListContext abt Pure -> abt '[] a
+ Language.Hakaru.Evaluation.EvalMonad: runEval :: (ABT Term abt, Foldable f) => Eval abt (abt '[] a) -> f (Some2 abt) -> abt '[] a
+ Language.Hakaru.Evaluation.EvalMonad: runPureEvaluate :: (ABT Term abt) => abt '[] a -> abt '[] a
+ Language.Hakaru.Evaluation.EvalMonad: type PureAns abt a = ListContext abt Pure -> abt '[] a
+ Language.Hakaru.Evaluation.ExpectMonad: Expect :: ((x -> ExpectAns abt) -> ExpectAns abt) -> Expect abt x
+ Language.Hakaru.Evaluation.ExpectMonad: ListContext :: {-# UNPACK #-} !Nat -> [Statement abt p] -> ListContext
+ Language.Hakaru.Evaluation.ExpectMonad: [nextFreshNat] :: ListContext -> {-# UNPACK #-} !Nat
+ Language.Hakaru.Evaluation.ExpectMonad: [statements] :: ListContext -> [Statement abt p]
+ Language.Hakaru.Evaluation.ExpectMonad: [unExpect] :: Expect abt x -> (x -> ExpectAns abt) -> ExpectAns abt
+ Language.Hakaru.Evaluation.ExpectMonad: data ListContext (abt :: [Hakaru] -> Hakaru -> *) (p :: Purity)
+ Language.Hakaru.Evaluation.ExpectMonad: emit :: (ABT Term abt) => Text -> Sing a -> (abt '[a] HProb -> abt '[] HProb) -> Expect abt (Variable a)
+ Language.Hakaru.Evaluation.ExpectMonad: emit_ :: (ABT Term abt) => (abt '[] HProb -> abt '[] HProb) -> Expect abt ()
+ Language.Hakaru.Evaluation.ExpectMonad: instance GHC.Base.Applicative (Language.Hakaru.Evaluation.ExpectMonad.Expect abt)
+ Language.Hakaru.Evaluation.ExpectMonad: instance GHC.Base.Functor (Language.Hakaru.Evaluation.ExpectMonad.Expect abt)
+ Language.Hakaru.Evaluation.ExpectMonad: instance GHC.Base.Monad (Language.Hakaru.Evaluation.ExpectMonad.Expect abt)
+ Language.Hakaru.Evaluation.ExpectMonad: instance Language.Hakaru.Syntax.ABT.ABT Language.Hakaru.Syntax.AST.Term abt => Language.Hakaru.Evaluation.Types.EvaluationMonad abt (Language.Hakaru.Evaluation.ExpectMonad.Expect abt) 'Language.Hakaru.Evaluation.Types.ExpectP
+ Language.Hakaru.Evaluation.ExpectMonad: newtype Expect abt x
+ Language.Hakaru.Evaluation.ExpectMonad: pureEvaluate :: (ABT Term abt) => TermEvaluator abt (Expect abt)
+ Language.Hakaru.Evaluation.ExpectMonad: residualizeExpectListContext :: forall abt. (ABT Term abt) => abt '[] HProb -> ListContext abt ExpectP -> abt '[] HProb
+ Language.Hakaru.Evaluation.ExpectMonad: runExpect :: forall abt f a. (ABT Term abt, Foldable f) => Expect abt (abt '[] a) -> abt '[a] HProb -> f (Some2 abt) -> abt '[] HProb
+ Language.Hakaru.Evaluation.ExpectMonad: type ExpectAns abt = ListContext abt ExpectP -> abt '[] HProb
+ Language.Hakaru.Evaluation.Lazy: class Interp a a' | a -> a'
+ Language.Hakaru.Evaluation.Lazy: defaultCaseEvaluator :: forall abt m p. (ABT Term abt, EvaluationMonad abt m p) => TermEvaluator abt m -> CaseEvaluator abt m
+ Language.Hakaru.Evaluation.Lazy: evaluate :: forall abt m p. (ABT Term abt, EvaluationMonad abt m p) => MeasureEvaluator abt m -> (TermEvaluator abt m -> CaseEvaluator abt m) -> TermEvaluator abt m
+ Language.Hakaru.Evaluation.Lazy: instance Language.Hakaru.Evaluation.Lazy.Interp 'Language.Hakaru.Types.DataKind.HInt GHC.Integer.Type.Integer
+ Language.Hakaru.Evaluation.Lazy: instance Language.Hakaru.Evaluation.Lazy.Interp 'Language.Hakaru.Types.DataKind.HNat Data.Number.Natural.Natural
+ Language.Hakaru.Evaluation.Lazy: instance Language.Hakaru.Evaluation.Lazy.Interp 'Language.Hakaru.Types.DataKind.HProb Data.Number.Natural.NonNegativeRational
+ Language.Hakaru.Evaluation.Lazy: instance Language.Hakaru.Evaluation.Lazy.Interp 'Language.Hakaru.Types.DataKind.HReal GHC.Real.Rational
+ Language.Hakaru.Evaluation.Lazy: instance Language.Hakaru.Evaluation.Lazy.Interp Language.Hakaru.Types.DataKind.HBool GHC.Types.Bool
+ Language.Hakaru.Evaluation.Lazy: instance Language.Hakaru.Evaluation.Lazy.Interp Language.Hakaru.Types.DataKind.HUnit ()
+ Language.Hakaru.Evaluation.Lazy: reflect :: (Interp a a', ABT Term abt) => a' -> Head abt a
+ Language.Hakaru.Evaluation.Lazy: reify :: (Interp a a', ABT Term abt) => Head abt a -> a'
+ Language.Hakaru.Evaluation.Lazy: reifyPair :: (ABT Term abt) => Head abt (HPair a b) -> (abt '[] a, abt '[] b)
+ Language.Hakaru.Evaluation.Lazy: toStatements :: Assocs (abt '[]) -> [Statement abt p]
+ Language.Hakaru.Evaluation.Lazy: type CaseEvaluator abt m = forall a b. abt '[] a -> [Branch a abt b] -> m (Whnf abt b)
+ Language.Hakaru.Evaluation.Lazy: type MeasureEvaluator abt m = forall a. abt '[] (HMeasure a) -> m (Whnf abt a)
+ Language.Hakaru.Evaluation.Lazy: type TermEvaluator abt m = forall a. abt '[] a -> m (Whnf abt a)
+ Language.Hakaru.Evaluation.Lazy: type VariableEvaluator abt m = forall a. Variable a -> m (Whnf abt a)
+ Language.Hakaru.Evaluation.Lazy: update :: forall abt m p. (ABT Term abt, EvaluationMonad abt m p) => MeasureEvaluator abt m -> TermEvaluator abt m -> VariableEvaluator abt m
+ Language.Hakaru.Evaluation.PEvalMonad: ListContext :: {-# UNPACK #-} !Nat -> [Statement abt p] -> ListContext
+ Language.Hakaru.Evaluation.PEvalMonad: PEval :: (forall a. (x -> PAns p abt m a) -> PAns p abt m a) -> PEval abt p m x
+ Language.Hakaru.Evaluation.PEvalMonad: [nextFreshNat] :: ListContext -> {-# UNPACK #-} !Nat
+ Language.Hakaru.Evaluation.PEvalMonad: [statements] :: ListContext -> [Statement abt p]
+ Language.Hakaru.Evaluation.PEvalMonad: [unPEval] :: PEval abt p m x -> forall a. (x -> PAns p abt m a) -> PAns p abt m a
+ Language.Hakaru.Evaluation.PEvalMonad: bot :: (ABT Term abt, Alternative m) => PEval abt p m a
+ Language.Hakaru.Evaluation.PEvalMonad: choose :: (ABT Term abt, Applicative m) => [PEval abt Impure m a] -> PEval abt Impure m a
+ Language.Hakaru.Evaluation.PEvalMonad: data ListContext (abt :: [Hakaru] -> Hakaru -> *) (p :: Purity)
+ Language.Hakaru.Evaluation.PEvalMonad: emit :: (ABT Term abt, Functor m) => Text -> Sing a -> (forall r. P p abt '[a] r -> P p abt '[] r) -> PEval abt p m (Variable a)
+ Language.Hakaru.Evaluation.PEvalMonad: emitFork_ :: (ABT Term abt, Applicative m, Traversable t) => (forall r. t (P p abt '[] r) -> P p abt '[] r) -> t (PEval abt p m a) -> PEval abt p m a
+ Language.Hakaru.Evaluation.PEvalMonad: emitGuard :: (ABT Term abt, Functor m) => abt '[] HBool -> PEval abt Impure m ()
+ Language.Hakaru.Evaluation.PEvalMonad: emitLet :: (ABT Term abt, Functor m) => abt '[] a -> PEval abt p m (Variable a)
+ Language.Hakaru.Evaluation.PEvalMonad: emitLet' :: (ABT Term abt, Functor m) => abt '[] a -> PEval abt p m (abt '[] a)
+ Language.Hakaru.Evaluation.PEvalMonad: emitMBind :: (ABT Term abt, Functor m) => abt '[] (HMeasure a) -> PEval abt Impure m (Variable a)
+ Language.Hakaru.Evaluation.PEvalMonad: emitMBind_ :: (ABT Term abt, Functor m) => abt '[] (HMeasure HUnit) -> PEval abt Impure m ()
+ Language.Hakaru.Evaluation.PEvalMonad: emitSuperpose :: (ABT Term abt, Functor m) => [abt '[] (HMeasure a)] -> PEval abt Impure m (Variable a)
+ Language.Hakaru.Evaluation.PEvalMonad: emitUnpair :: (ABT Term abt, Applicative m) => Whnf abt (HPair a b) -> PEval abt p m (abt '[] a, abt '[] b)
+ Language.Hakaru.Evaluation.PEvalMonad: emitWeight :: (ABT Term abt, Functor m) => abt '[] HProb -> PEval abt Impure m ()
+ Language.Hakaru.Evaluation.PEvalMonad: emit_ :: (ABT Term abt, Functor m) => (forall r. P p abt '[] r -> P p abt '[] r) -> PEval abt p m ()
+ Language.Hakaru.Evaluation.PEvalMonad: instance GHC.Base.Alternative m => GHC.Base.Alternative (Language.Hakaru.Evaluation.PEvalMonad.PEval abt p m)
+ Language.Hakaru.Evaluation.PEvalMonad: instance GHC.Base.Alternative m => GHC.Base.MonadPlus (Language.Hakaru.Evaluation.PEvalMonad.PEval abt p m)
+ Language.Hakaru.Evaluation.PEvalMonad: instance GHC.Base.Applicative (Language.Hakaru.Evaluation.PEvalMonad.PEval abt p m)
+ Language.Hakaru.Evaluation.PEvalMonad: instance GHC.Base.Functor (Language.Hakaru.Evaluation.PEvalMonad.PEval abt p m)
+ Language.Hakaru.Evaluation.PEvalMonad: instance GHC.Base.Monad (Language.Hakaru.Evaluation.PEvalMonad.PEval abt p m)
+ Language.Hakaru.Evaluation.PEvalMonad: instance Language.Hakaru.Syntax.ABT.ABT Language.Hakaru.Syntax.AST.Term abt => Language.Hakaru.Evaluation.Types.EvaluationMonad abt (Language.Hakaru.Evaluation.PEvalMonad.PEval abt p m) p
+ Language.Hakaru.Evaluation.PEvalMonad: newtype PEval abt p m x
+ Language.Hakaru.Evaluation.PEvalMonad: runExpectEval :: (ABT Term abt, Applicative m, Foldable f) => PEval abt ExpectP m (abt '[] a) -> abt '[a] HProb -> f (Some2 abt) -> m (abt '[] HProb)
+ Language.Hakaru.Evaluation.PEvalMonad: runImpureEval :: (ABT Term abt, Applicative m, Foldable f) => PEval abt Impure m (abt '[] a) -> f (Some2 abt) -> m (abt '[] (HMeasure a))
+ Language.Hakaru.Evaluation.PEvalMonad: runPureEval :: (ABT Term abt, Applicative m, Foldable f) => PEval abt Pure m (abt '[] a) -> f (Some2 abt) -> m (abt '[] a)
+ Language.Hakaru.Evaluation.PEvalMonad: type PAns p abt m a = ListContext abt p -> m (P p abt '[] a)
+ Language.Hakaru.Evaluation.Types: ExpectP :: Purity
+ Language.Hakaru.Evaluation.Types: Head_ :: !(Head abt a) -> Whnf
+ Language.Hakaru.Evaluation.Types: Hint :: {-# UNPACK #-} !Text -> !(Sing a) -> Hint
+ Language.Hakaru.Evaluation.Types: Impure :: Purity
+ Language.Hakaru.Evaluation.Types: Neutral :: !(abt '[] a) -> Whnf
+ Language.Hakaru.Evaluation.Types: Pure :: Purity
+ Language.Hakaru.Evaluation.Types: Thunk :: !(abt '[] a) -> Lazy
+ Language.Hakaru.Evaluation.Types: Whnf_ :: !(Whnf abt a) -> Lazy
+ Language.Hakaru.Evaluation.Types: [SBind] :: forall abt (a :: Hakaru). {-# UNPACK #-} !(Variable a) -> !(Lazy abt (HMeasure a)) -> [Index (abt '[])] -> Statement abt Impure
+ Language.Hakaru.Evaluation.Types: [SGuard] :: forall abt (xs :: [Hakaru]) (a :: Hakaru). !(List1 Variable xs) -> !(Pattern xs a) -> !(Lazy abt a) -> [Index (abt '[])] -> Statement abt Impure
+ Language.Hakaru.Evaluation.Types: [SLet] :: forall abt p (a :: Hakaru). {-# UNPACK #-} !(Variable a) -> !(Lazy abt a) -> [Index (abt '[])] -> Statement abt p
+ Language.Hakaru.Evaluation.Types: [SStuff0] :: forall abt. (abt '[] HProb -> abt '[] HProb) -> [Index (abt '[])] -> Statement abt ExpectP
+ Language.Hakaru.Evaluation.Types: [SStuff1] :: forall abt (a :: Hakaru). {-# UNPACK #-} !(Variable a) -> (abt '[] HProb -> abt '[] HProb) -> [Index (abt '[])] -> Statement abt ExpectP
+ Language.Hakaru.Evaluation.Types: [SWeight] :: forall abt. !(Lazy abt HProb) -> [Index (abt '[])] -> Statement abt Impure
+ Language.Hakaru.Evaluation.Types: [WArray] :: !(abt '[] HNat) -> !(abt '[HNat] a) -> Head abt (HArray a)
+ Language.Hakaru.Evaluation.Types: [WChain] :: !(abt '[] HNat) -> !(abt '[] s) -> !(abt '[s] (HMeasure (HPair a s))) -> Head abt (HMeasure (HPair (HArray a) s))
+ Language.Hakaru.Evaluation.Types: [WCoerceTo] :: !(Coercion a b) -> !(Head abt a) -> Head abt b
+ Language.Hakaru.Evaluation.Types: [WDatum] :: !(Datum (abt '[]) (HData' t)) -> Head abt (HData' t)
+ Language.Hakaru.Evaluation.Types: [WDirac] :: !(abt '[] a) -> Head abt (HMeasure a)
+ Language.Hakaru.Evaluation.Types: [WEmpty] :: !(Sing (HArray a)) -> Head abt (HArray a)
+ Language.Hakaru.Evaluation.Types: [WIntegrate] :: !(abt '[] HReal) -> !(abt '[] HReal) -> !(abt '[HReal] HProb) -> Head abt HProb
+ Language.Hakaru.Evaluation.Types: [WLam] :: !(abt '[a] b) -> Head abt (a :-> b)
+ Language.Hakaru.Evaluation.Types: [WLiteral] :: !(Literal a) -> Head abt a
+ Language.Hakaru.Evaluation.Types: [WMBind] :: !(abt '[] (HMeasure a)) -> !(abt '[a] (HMeasure b)) -> Head abt (HMeasure b)
+ Language.Hakaru.Evaluation.Types: [WMeasureOp] :: (typs ~ UnLCs args, args ~ LCs typs) => !(MeasureOp typs a) -> !(SArgs abt args) -> Head abt (HMeasure a)
+ Language.Hakaru.Evaluation.Types: [WPlate] :: !(abt '[] HNat) -> !(abt '[HNat] (HMeasure a)) -> Head abt (HMeasure (HArray a))
+ Language.Hakaru.Evaluation.Types: [WReject] :: !(Sing (HMeasure a)) -> Head abt (HMeasure a)
+ Language.Hakaru.Evaluation.Types: [WSuperpose] :: !(NonEmpty (abt '[] HProb, abt '[] (HMeasure a))) -> Head abt (HMeasure a)
+ Language.Hakaru.Evaluation.Types: [WUnsafeFrom] :: !(Coercion a b) -> !(Head abt b) -> Head abt a
+ Language.Hakaru.Evaluation.Types: caseLazy :: Lazy abt a -> (Whnf abt a -> r) -> (abt '[] a -> r) -> r
+ Language.Hakaru.Evaluation.Types: caseWhnf :: Whnf abt a -> (Head abt a -> r) -> (abt '[] a -> r) -> r
+ Language.Hakaru.Evaluation.Types: class (Functor m, Applicative m, Monad m, ABT Term abt) => EvaluationMonad abt m p | m -> abt p where freshenStatement s = case s of { SWeight _ _ -> return (s, mempty) SBind x body i -> do { x' <- freshenVar x; return (SBind x' body i, singletonAssocs x x') } SLet x body i -> do { x' <- freshenVar x; return (SLet x' body i, singletonAssocs x x') } SGuard xs pat scrutinee i -> do { xs' <- freshenVars xs; return (SGuard xs' pat scrutinee i, toAssocs1 xs xs') } SStuff0 _ _ -> return (s, mempty) SStuff1 x f i -> do { x' <- freshenVar x; return (SStuff1 x' f i, singletonAssocs x x') } } getIndices = return [] unsafePushes = mapM_ unsafePush
+ Language.Hakaru.Evaluation.Types: data Head :: ([Hakaru] -> Hakaru -> *) -> Hakaru -> *
+ Language.Hakaru.Evaluation.Types: data Hint (a :: Hakaru)
+ Language.Hakaru.Evaluation.Types: data Index ast
+ Language.Hakaru.Evaluation.Types: data Lazy (abt :: [Hakaru] -> Hakaru -> *) (a :: Hakaru)
+ Language.Hakaru.Evaluation.Types: data Purity
+ Language.Hakaru.Evaluation.Types: data Statement :: ([Hakaru] -> Hakaru -> *) -> Purity -> *
+ Language.Hakaru.Evaluation.Types: data Whnf (abt :: [Hakaru] -> Hakaru -> *) (a :: Hakaru)
+ Language.Hakaru.Evaluation.Types: freshInd :: (EvaluationMonad abt m p) => abt '[] HNat -> m (Index (abt '[]))
+ Language.Hakaru.Evaluation.Types: freshNat :: EvaluationMonad abt m p => m Nat
+ Language.Hakaru.Evaluation.Types: freshVar :: (EvaluationMonad abt m p) => Text -> Sing (a :: Hakaru) -> m (Variable a)
+ Language.Hakaru.Evaluation.Types: freshVars :: (EvaluationMonad abt m p) => List1 Hint xs -> m (List1 Variable xs)
+ Language.Hakaru.Evaluation.Types: freshenStatement :: EvaluationMonad abt m p => Statement abt p -> m (Statement abt p, Assocs (Variable :: Hakaru -> *))
+ Language.Hakaru.Evaluation.Types: freshenVar :: (EvaluationMonad abt m p) => Variable (a :: Hakaru) -> m (Variable a)
+ Language.Hakaru.Evaluation.Types: freshenVars :: (EvaluationMonad abt m p) => List1 Variable (xs :: [Hakaru]) -> m (List1 Variable xs)
+ Language.Hakaru.Evaluation.Types: fromHead :: (ABT Term abt) => Head abt a -> abt '[] a
+ Language.Hakaru.Evaluation.Types: fromLazy :: (ABT Term abt) => Lazy abt a -> abt '[] a
+ Language.Hakaru.Evaluation.Types: fromWhnf :: (ABT Term abt) => Whnf abt a -> abt '[] a
+ Language.Hakaru.Evaluation.Types: getIndices :: EvaluationMonad abt m p => m [Index (abt '[])]
+ Language.Hakaru.Evaluation.Types: getLazyLiteral :: (ABT Term abt) => Lazy abt a -> Maybe (Literal a)
+ Language.Hakaru.Evaluation.Types: getLazyVariable :: (ABT Term abt) => Lazy abt a -> Maybe (Variable a)
+ Language.Hakaru.Evaluation.Types: indSize :: Index ast -> ast HNat
+ Language.Hakaru.Evaluation.Types: indVar :: Index ast -> Variable HNat
+ Language.Hakaru.Evaluation.Types: instance GHC.Classes.Eq Language.Hakaru.Evaluation.Types.Purity
+ Language.Hakaru.Evaluation.Types: instance GHC.Read.Read Language.Hakaru.Evaluation.Types.Purity
+ Language.Hakaru.Evaluation.Types: instance GHC.Show.Show Language.Hakaru.Evaluation.Types.Purity
+ Language.Hakaru.Evaluation.Types: instance Language.Hakaru.Syntax.ABT.ABT Language.Hakaru.Syntax.AST.Term abt => GHC.Classes.Eq (Language.Hakaru.Evaluation.Types.Index (abt '[]))
+ Language.Hakaru.Evaluation.Types: instance Language.Hakaru.Syntax.ABT.ABT Language.Hakaru.Syntax.AST.Term abt => GHC.Classes.Ord (Language.Hakaru.Evaluation.Types.Index (abt '[]))
+ Language.Hakaru.Evaluation.Types: instance Language.Hakaru.Syntax.ABT.ABT Language.Hakaru.Syntax.AST.Term abt => Language.Hakaru.Types.Coercion.Coerce (Language.Hakaru.Evaluation.Types.Whnf abt)
+ Language.Hakaru.Evaluation.Types: instance Language.Hakaru.Syntax.IClasses.Foldable21 Language.Hakaru.Evaluation.Types.Head
+ Language.Hakaru.Evaluation.Types: instance Language.Hakaru.Syntax.IClasses.Foldable21 Language.Hakaru.Evaluation.Types.Lazy
+ Language.Hakaru.Evaluation.Types: instance Language.Hakaru.Syntax.IClasses.Foldable21 Language.Hakaru.Evaluation.Types.Whnf
+ Language.Hakaru.Evaluation.Types: instance Language.Hakaru.Syntax.IClasses.Functor21 Language.Hakaru.Evaluation.Types.Head
+ Language.Hakaru.Evaluation.Types: instance Language.Hakaru.Syntax.IClasses.Functor21 Language.Hakaru.Evaluation.Types.Lazy
+ Language.Hakaru.Evaluation.Types: instance Language.Hakaru.Syntax.IClasses.Functor21 Language.Hakaru.Evaluation.Types.Whnf
+ Language.Hakaru.Evaluation.Types: instance Language.Hakaru.Syntax.IClasses.Traversable21 Language.Hakaru.Evaluation.Types.Head
+ Language.Hakaru.Evaluation.Types: instance Language.Hakaru.Syntax.IClasses.Traversable21 Language.Hakaru.Evaluation.Types.Lazy
+ Language.Hakaru.Evaluation.Types: instance Language.Hakaru.Syntax.IClasses.Traversable21 Language.Hakaru.Evaluation.Types.Whnf
+ Language.Hakaru.Evaluation.Types: isBoundBy :: Variable (a :: Hakaru) -> Statement abt p -> Maybe ()
+ Language.Hakaru.Evaluation.Types: isLazyLiteral :: (ABT Term abt) => Lazy abt a -> Bool
+ Language.Hakaru.Evaluation.Types: isLazyVariable :: (ABT Term abt) => Lazy abt a -> Bool
+ Language.Hakaru.Evaluation.Types: push :: (ABT Term abt, EvaluationMonad abt m p) => Statement abt p -> abt xs a -> (abt xs a -> m r) -> m r
+ Language.Hakaru.Evaluation.Types: pushes :: (ABT Term abt, EvaluationMonad abt m p) => [Statement abt p] -> abt xs a -> (abt xs a -> m r) -> m r
+ Language.Hakaru.Evaluation.Types: select :: EvaluationMonad abt m p => Variable (a :: Hakaru) -> (Statement abt p -> Maybe (m r)) -> m (Maybe r)
+ Language.Hakaru.Evaluation.Types: statementVars :: Statement abt p -> VarSet (KProxy :: KProxy Hakaru)
+ Language.Hakaru.Evaluation.Types: toHead :: (ABT Term abt) => abt '[] a -> Maybe (Head abt a)
+ Language.Hakaru.Evaluation.Types: toWhnf :: (ABT Term abt) => abt '[] a -> Maybe (Whnf abt a)
+ Language.Hakaru.Evaluation.Types: unsafePush :: EvaluationMonad abt m p => Statement abt p -> m ()
+ Language.Hakaru.Evaluation.Types: unsafePushes :: EvaluationMonad abt m p => [Statement abt p] -> m ()
+ Language.Hakaru.Evaluation.Types: viewHeadDatum :: (ABT Term abt) => Head abt (HData' t) -> Datum (abt '[]) (HData' t)
+ Language.Hakaru.Evaluation.Types: viewWhnfDatum :: (ABT Term abt) => Whnf abt (HData' t) -> Maybe (Datum (abt '[]) (HData' t))
+ Language.Hakaru.Expect: expect :: (ABT Term abt) => abt '[] (HMeasure a) -> abt '[a] HProb -> abt '[] HProb
+ Language.Hakaru.Expect: normalize :: (ABT Term abt) => abt '[] (HMeasure a) -> abt '[] (HMeasure a)
+ Language.Hakaru.Expect: total :: (ABT Term abt) => abt '[] (HMeasure a) -> abt '[] HProb
+ Language.Hakaru.Inference: approxMh :: (ABT Term abt, SingI a) => (abt '[] a -> abt '[] (HMeasure a)) -> abt '[] (HMeasure a) -> [abt '[] a -> abt '[] (HMeasure a)] -> abt '[] (a :-> HMeasure a)
+ Language.Hakaru.Inference: gibbsProposal :: (ABT Term abt, SingI a, SingI b) => abt '[] (HMeasure (HPair a b)) -> abt '[] (HPair a b) -> abt '[] (HMeasure (HPair a b))
+ Language.Hakaru.Inference: incompleteBeta :: (ABT Term abt) => abt '[] HProb -> abt '[] HProb -> abt '[] HProb -> abt '[] HProb
+ Language.Hakaru.Inference: kl :: (ABT Term abt) => abt '[] (HMeasure a) -> abt '[] (HMeasure a) -> Maybe (abt '[] HProb)
+ Language.Hakaru.Inference: mcmc :: (ABT Term abt) => abt '[] (a :-> HMeasure a) -> abt '[] (HMeasure a) -> abt '[] (a :-> HMeasure a)
+ Language.Hakaru.Inference: mh :: (ABT Term abt) => abt '[] (a :-> HMeasure a) -> abt '[] (HMeasure a) -> abt '[] (a :-> HMeasure (HPair a HProb))
+ Language.Hakaru.Inference: priorAsProposal :: (ABT Term abt, SingI a, SingI b) => abt '[] (HMeasure (HPair a b)) -> abt '[] (HPair a b) -> abt '[] (HMeasure (HPair a b))
+ Language.Hakaru.Inference: regBeta :: (ABT Term abt) => abt '[] HProb -> abt '[] HProb -> abt '[] HProb -> abt '[] HProb
+ Language.Hakaru.Inference: slice :: (ABT Term abt) => abt '[] (HMeasure HReal) -> abt '[] (HReal :-> HMeasure HReal)
+ Language.Hakaru.Inference: sliceX :: (ABT Term abt, SingI a) => abt '[] (HMeasure a) -> abt '[] (HMeasure (HPair a HReal))
+ Language.Hakaru.Inference: tCDF :: (ABT Term abt) => abt '[] HReal -> abt '[] HProb -> abt '[] HProb
+ Language.Hakaru.Observe: freshenVarRe :: ABT syn abt => Variable (a :: k) -> abt '[] (b :: k) -> Variable a
+ Language.Hakaru.Observe: observe :: (ABT Term abt) => abt '[] (HMeasure a) -> abt '[] a -> abt '[] (HMeasure a)
+ Language.Hakaru.Observe: observeAST :: (ABT Term abt) => LC_ abt (HMeasure a) -> LC_ abt a -> abt '[] (HMeasure a)
+ Language.Hakaru.Observe: observeMeasureOp :: (ABT Term abt, typs ~ UnLCs args, args ~ LCs typs) => MeasureOp typs a -> SArgs abt args -> abt '[] a -> abt '[] (HMeasure a)
+ Language.Hakaru.Observe: observeVar :: a
+ Language.Hakaru.Parser.AST: ASTWithImport' :: [Import a] -> (AST' a) -> ASTWithImport' a
+ Language.Hakaru.Parser.AST: Abs :: PrimOp
+ Language.Hakaru.Parser.AST: Acos :: PrimOp
+ Language.Hakaru.Parser.AST: Acosh :: PrimOp
+ Language.Hakaru.Parser.AST: And :: NaryOp
+ Language.Hakaru.Parser.AST: Ann :: (AST' a) -> TypeAST' -> AST' a
+ Language.Hakaru.Parser.AST: App :: (AST' a) -> (AST' a) -> AST' a
+ Language.Hakaru.Parser.AST: Array :: a -> (AST' a) -> (AST' a) -> AST' a
+ Language.Hakaru.Parser.AST: Asin :: PrimOp
+ Language.Hakaru.Parser.AST: Asinh :: PrimOp
+ Language.Hakaru.Parser.AST: Atan :: PrimOp
+ Language.Hakaru.Parser.AST: Atanh :: PrimOp
+ Language.Hakaru.Parser.AST: BetaFunc :: PrimOp
+ Language.Hakaru.Parser.AST: Bind :: a -> (AST' a) -> (AST' a) -> AST' a
+ Language.Hakaru.Parser.AST: Branch' :: (Pattern' Name') -> (AST' a) -> Branch' a
+ Language.Hakaru.Parser.AST: Branch'' :: (Pattern' Name) -> (AST' a) -> Branch' a
+ Language.Hakaru.Parser.AST: Branch_ :: Pattern -> (abt '[] U) -> Branch_ abt
+ Language.Hakaru.Parser.AST: Case :: (AST' a) -> [(Branch' a)] -> AST' a
+ Language.Hakaru.Parser.AST: Chain :: a -> (AST' a) -> (AST' a) -> (AST' a) -> AST' a
+ Language.Hakaru.Parser.AST: Cos :: PrimOp
+ Language.Hakaru.Parser.AST: Cosh :: PrimOp
+ Language.Hakaru.Parser.AST: DV :: Name' -> [Pattern' a] -> PDatum a
+ Language.Hakaru.Parser.AST: Data :: a -> [TypeAST'] -> AST' a
+ Language.Hakaru.Parser.AST: Datum :: Text -> (DCode abt) -> Datum abt
+ Language.Hakaru.Parser.AST: Diff :: PrimOp
+ Language.Hakaru.Parser.AST: Dirac :: (AST' a) -> AST' a
+ Language.Hakaru.Parser.AST: Done :: DStruct abt
+ Language.Hakaru.Parser.AST: Empty :: AST' a
+ Language.Hakaru.Parser.AST: Equal :: PrimOp
+ Language.Hakaru.Parser.AST: Erf :: PrimOp
+ Language.Hakaru.Parser.AST: Et :: (DFun abt) -> (DStruct abt) -> DStruct abt
+ Language.Hakaru.Parser.AST: Exp :: PrimOp
+ Language.Hakaru.Parser.AST: Expect :: a -> (AST' a) -> (AST' a) -> AST' a
+ Language.Hakaru.Parser.AST: GammaFunc :: PrimOp
+ Language.Hakaru.Parser.AST: Ident :: (abt '[] U) -> DFun abt
+ Language.Hakaru.Parser.AST: If :: (AST' a) -> (AST' a) -> (AST' a) -> AST' a
+ Language.Hakaru.Parser.AST: Iff :: NaryOp
+ Language.Hakaru.Parser.AST: Impl :: PrimOp
+ Language.Hakaru.Parser.AST: Import :: a -> Import a
+ Language.Hakaru.Parser.AST: Index :: (AST' a) -> (AST' a) -> AST' a
+ Language.Hakaru.Parser.AST: Index_ :: ArrayOp
+ Language.Hakaru.Parser.AST: Infinity :: PrimOp
+ Language.Hakaru.Parser.AST: Infinity' :: AST' a
+ Language.Hakaru.Parser.AST: Inl :: (DStruct abt) -> DCode abt
+ Language.Hakaru.Parser.AST: Inr :: (DCode abt) -> DCode abt
+ Language.Hakaru.Parser.AST: Int :: Integer -> Literal'
+ Language.Hakaru.Parser.AST: Integrate :: a -> (AST' a) -> (AST' a) -> (AST' a) -> AST' a
+ Language.Hakaru.Parser.AST: Konst :: (abt '[] U) -> DFun abt
+ Language.Hakaru.Parser.AST: Lam :: a -> TypeAST' -> (AST' a) -> AST' a
+ Language.Hakaru.Parser.AST: Less :: PrimOp
+ Language.Hakaru.Parser.AST: Let :: a -> (AST' a) -> (AST' a) -> AST' a
+ Language.Hakaru.Parser.AST: Log :: PrimOp
+ Language.Hakaru.Parser.AST: Max :: NaryOp
+ Language.Hakaru.Parser.AST: Min :: NaryOp
+ Language.Hakaru.Parser.AST: Msum :: [AST' a] -> AST' a
+ Language.Hakaru.Parser.AST: Name :: {-# UNPACK #-} !Nat -> {-# UNPACK #-} !Text -> Name
+ Language.Hakaru.Parser.AST: Nand :: PrimOp
+ Language.Hakaru.Parser.AST: NaryOp :: NaryOp -> [AST' a] -> AST' a
+ Language.Hakaru.Parser.AST: Nat :: Integer -> Literal'
+ Language.Hakaru.Parser.AST: NatPow :: PrimOp
+ Language.Hakaru.Parser.AST: NatRoot :: PrimOp
+ Language.Hakaru.Parser.AST: Negate :: PrimOp
+ Language.Hakaru.Parser.AST: Nor :: PrimOp
+ Language.Hakaru.Parser.AST: Not :: PrimOp
+ Language.Hakaru.Parser.AST: Observe :: (AST' a) -> (AST' a) -> AST' a
+ Language.Hakaru.Parser.AST: Or :: NaryOp
+ Language.Hakaru.Parser.AST: PData' :: (PDatum a) -> Pattern' a
+ Language.Hakaru.Parser.AST: PDatum :: Text -> PCode -> Pattern
+ Language.Hakaru.Parser.AST: PDone :: PStruct
+ Language.Hakaru.Parser.AST: PEt :: PFun -> PStruct -> PStruct
+ Language.Hakaru.Parser.AST: PIdent :: Pattern -> PFun
+ Language.Hakaru.Parser.AST: PInl :: PStruct -> PCode
+ Language.Hakaru.Parser.AST: PInr :: PCode -> PCode
+ Language.Hakaru.Parser.AST: PKonst :: Pattern -> PFun
+ Language.Hakaru.Parser.AST: PVar :: Name -> Pattern
+ Language.Hakaru.Parser.AST: PVar' :: a -> Pattern' a
+ Language.Hakaru.Parser.AST: PWild :: Pattern
+ Language.Hakaru.Parser.AST: PWild' :: Pattern' a
+ Language.Hakaru.Parser.AST: Pair :: (AST' a) -> (AST' a) -> AST' a
+ Language.Hakaru.Parser.AST: Pi :: PrimOp
+ Language.Hakaru.Parser.AST: Plate :: a -> (AST' a) -> (AST' a) -> AST' a
+ Language.Hakaru.Parser.AST: Prob :: Rational -> Literal'
+ Language.Hakaru.Parser.AST: Prod :: NaryOp
+ Language.Hakaru.Parser.AST: Product :: a -> (AST' a) -> (AST' a) -> (AST' a) -> AST' a
+ Language.Hakaru.Parser.AST: Real :: Rational -> Literal'
+ Language.Hakaru.Parser.AST: RealPow :: PrimOp
+ Language.Hakaru.Parser.AST: Recip :: PrimOp
+ Language.Hakaru.Parser.AST: Reduce :: ArrayOp
+ Language.Hakaru.Parser.AST: SSing :: !(Sing a) -> SSing
+ Language.Hakaru.Parser.AST: Signum :: PrimOp
+ Language.Hakaru.Parser.AST: Sin :: PrimOp
+ Language.Hakaru.Parser.AST: Sinh :: PrimOp
+ Language.Hakaru.Parser.AST: Size :: ArrayOp
+ Language.Hakaru.Parser.AST: SourceSpan :: !SourcePos -> !SourcePos -> SourceSpan
+ Language.Hakaru.Parser.AST: Sum :: NaryOp
+ Language.Hakaru.Parser.AST: Summate :: a -> (AST' a) -> (AST' a) -> (AST' a) -> AST' a
+ Language.Hakaru.Parser.AST: Tan :: PrimOp
+ Language.Hakaru.Parser.AST: Tanh :: PrimOp
+ Language.Hakaru.Parser.AST: TypeApp :: Name' -> [TypeAST'] -> TypeAST'
+ Language.Hakaru.Parser.AST: TypeFun :: TypeAST' -> TypeAST' -> TypeAST'
+ Language.Hakaru.Parser.AST: TypeVar :: Name' -> TypeAST'
+ Language.Hakaru.Parser.AST: U :: Untyped
+ Language.Hakaru.Parser.AST: ULiteral :: Literal' -> AST' a
+ Language.Hakaru.Parser.AST: Unit :: AST' a
+ Language.Hakaru.Parser.AST: Var :: a -> AST' a
+ Language.Hakaru.Parser.AST: WithMeta :: (AST' a) -> SourceSpan -> AST' a
+ Language.Hakaru.Parser.AST: Xor :: NaryOp
+ Language.Hakaru.Parser.AST: [Ann_] :: SSing -> abt '[] U -> Term abt U
+ Language.Hakaru.Parser.AST: [App_] :: abt '[] U -> abt '[] U -> Term abt U
+ Language.Hakaru.Parser.AST: [ArrayOp_] :: ArrayOp -> [abt '[] U] -> Term abt U
+ Language.Hakaru.Parser.AST: [Array_] :: abt '[] U -> abt '[U] U -> Term abt U
+ Language.Hakaru.Parser.AST: [Case_] :: abt '[] U -> [Branch_ abt] -> Term abt U
+ Language.Hakaru.Parser.AST: [Chain_] :: abt '[] U -> abt '[] U -> abt '[U] U -> Term abt U
+ Language.Hakaru.Parser.AST: [CoerceTo_] :: Some2 Coercion -> abt '[] U -> Term abt U
+ Language.Hakaru.Parser.AST: [Datum_] :: Datum abt -> Term abt U
+ Language.Hakaru.Parser.AST: [Dirac_] :: abt '[] U -> Term abt U
+ Language.Hakaru.Parser.AST: [Empty_] :: Term abt U
+ Language.Hakaru.Parser.AST: [Expect_] :: abt '[] U -> abt '[U] U -> Term abt U
+ Language.Hakaru.Parser.AST: [Integrate_] :: abt '[] U -> abt '[] U -> abt '[U] U -> Term abt U
+ Language.Hakaru.Parser.AST: [Lam_] :: SSing -> abt '[U] U -> Term abt U
+ Language.Hakaru.Parser.AST: [Let_] :: abt '[] U -> abt '[U] U -> Term abt U
+ Language.Hakaru.Parser.AST: [Literal_] :: Some1 Literal -> Term abt U
+ Language.Hakaru.Parser.AST: [MBind_] :: abt '[] U -> abt '[U] U -> Term abt U
+ Language.Hakaru.Parser.AST: [MeasureOp_] :: SomeOp MeasureOp -> [abt '[] U] -> Term abt U
+ Language.Hakaru.Parser.AST: [NaryOp_] :: NaryOp -> [abt '[] U] -> Term abt U
+ Language.Hakaru.Parser.AST: [Observe_] :: abt '[] U -> abt '[] U -> Term abt U
+ Language.Hakaru.Parser.AST: [Pair_] :: abt '[] U -> abt '[] U -> Term abt U
+ Language.Hakaru.Parser.AST: [Plate_] :: abt '[] U -> abt '[U] U -> Term abt U
+ Language.Hakaru.Parser.AST: [PrimOp_] :: PrimOp -> [abt '[] U] -> Term abt U
+ Language.Hakaru.Parser.AST: [Product_] :: abt '[] U -> abt '[] U -> abt '[U] U -> Term abt U
+ Language.Hakaru.Parser.AST: [Reject_] :: Term abt U
+ Language.Hakaru.Parser.AST: [SomeOp] :: (typs ~ UnLCs args, args ~ LCs typs) => !(op typs a) -> SomeOp op
+ Language.Hakaru.Parser.AST: [Summate_] :: abt '[] U -> abt '[] U -> abt '[U] U -> Term abt U
+ Language.Hakaru.Parser.AST: [Superpose_] :: NonEmpty (abt '[] U, abt '[] U) -> Term abt U
+ Language.Hakaru.Parser.AST: [UnsafeTo_] :: Some2 Coercion -> abt '[] U -> Term abt U
+ Language.Hakaru.Parser.AST: data AST' a
+ Language.Hakaru.Parser.AST: data ASTWithImport' a
+ Language.Hakaru.Parser.AST: data ArrayOp
+ Language.Hakaru.Parser.AST: data Branch' a
+ Language.Hakaru.Parser.AST: data Branch_ abt
+ Language.Hakaru.Parser.AST: data DCode abt
+ Language.Hakaru.Parser.AST: data DFun abt
+ Language.Hakaru.Parser.AST: data DStruct abt
+ Language.Hakaru.Parser.AST: data Datum abt
+ Language.Hakaru.Parser.AST: data Import a
+ Language.Hakaru.Parser.AST: data Literal'
+ Language.Hakaru.Parser.AST: data Name
+ Language.Hakaru.Parser.AST: data NaryOp
+ Language.Hakaru.Parser.AST: data PCode
+ Language.Hakaru.Parser.AST: data PDatum a
+ Language.Hakaru.Parser.AST: data PFun
+ Language.Hakaru.Parser.AST: data PStruct
+ Language.Hakaru.Parser.AST: data Pattern
+ Language.Hakaru.Parser.AST: data Pattern' a
+ Language.Hakaru.Parser.AST: data PrimOp
+ Language.Hakaru.Parser.AST: data SSing
+ Language.Hakaru.Parser.AST: data SomeOp op
+ Language.Hakaru.Parser.AST: data SourceSpan
+ Language.Hakaru.Parser.AST: data Term :: ([Untyped] -> Untyped -> *) -> Untyped -> *
+ Language.Hakaru.Parser.AST: data TypeAST'
+ Language.Hakaru.Parser.AST: data Untyped
+ Language.Hakaru.Parser.AST: fmapBranch :: (f '[] U -> g '[] U) -> Branch_ f -> Branch_ g
+ Language.Hakaru.Parser.AST: fmapDatum :: (f '[] U -> g '[] U) -> Datum f -> Datum g
+ Language.Hakaru.Parser.AST: foldBranch :: (abt '[] U -> m) -> Branch_ abt -> m
+ Language.Hakaru.Parser.AST: foldDatum :: (Monoid m) => (abt '[] U -> m) -> Datum abt -> m
+ Language.Hakaru.Parser.AST: hintID :: Name -> Text
+ Language.Hakaru.Parser.AST: instance GHC.Classes.Eq (Language.Hakaru.Types.Sing.Sing a)
+ Language.Hakaru.Parser.AST: instance GHC.Classes.Eq Language.Hakaru.Parser.AST.Literal'
+ Language.Hakaru.Parser.AST: instance GHC.Classes.Eq Language.Hakaru.Parser.AST.Name
+ Language.Hakaru.Parser.AST: instance GHC.Classes.Eq Language.Hakaru.Parser.AST.NaryOp
+ Language.Hakaru.Parser.AST: instance GHC.Classes.Eq Language.Hakaru.Parser.AST.PrimOp
+ Language.Hakaru.Parser.AST: instance GHC.Classes.Eq Language.Hakaru.Parser.AST.SourceSpan
+ Language.Hakaru.Parser.AST: instance GHC.Classes.Eq Language.Hakaru.Parser.AST.TypeAST'
+ Language.Hakaru.Parser.AST: instance GHC.Classes.Eq a => GHC.Classes.Eq (Language.Hakaru.Parser.AST.AST' a)
+ Language.Hakaru.Parser.AST: instance GHC.Classes.Eq a => GHC.Classes.Eq (Language.Hakaru.Parser.AST.ASTWithImport' a)
+ Language.Hakaru.Parser.AST: instance GHC.Classes.Eq a => GHC.Classes.Eq (Language.Hakaru.Parser.AST.Branch' a)
+ Language.Hakaru.Parser.AST: instance GHC.Classes.Eq a => GHC.Classes.Eq (Language.Hakaru.Parser.AST.Import a)
+ Language.Hakaru.Parser.AST: instance GHC.Classes.Eq a => GHC.Classes.Eq (Language.Hakaru.Parser.AST.PDatum a)
+ Language.Hakaru.Parser.AST: instance GHC.Classes.Eq a => GHC.Classes.Eq (Language.Hakaru.Parser.AST.Pattern' a)
+ Language.Hakaru.Parser.AST: instance GHC.Classes.Ord Language.Hakaru.Parser.AST.Name
+ Language.Hakaru.Parser.AST: instance GHC.Read.Read Language.Hakaru.Parser.AST.Name
+ Language.Hakaru.Parser.AST: instance GHC.Read.Read Language.Hakaru.Parser.AST.Untyped
+ Language.Hakaru.Parser.AST: instance GHC.Show.Show (Language.Hakaru.Types.Sing.Sing a)
+ Language.Hakaru.Parser.AST: instance GHC.Show.Show Language.Hakaru.Parser.AST.Literal'
+ Language.Hakaru.Parser.AST: instance GHC.Show.Show Language.Hakaru.Parser.AST.Name
+ Language.Hakaru.Parser.AST: instance GHC.Show.Show Language.Hakaru.Parser.AST.NaryOp
+ Language.Hakaru.Parser.AST: instance GHC.Show.Show Language.Hakaru.Parser.AST.PrimOp
+ Language.Hakaru.Parser.AST: instance GHC.Show.Show Language.Hakaru.Parser.AST.SourceSpan
+ Language.Hakaru.Parser.AST: instance GHC.Show.Show Language.Hakaru.Parser.AST.TypeAST'
+ Language.Hakaru.Parser.AST: instance GHC.Show.Show Language.Hakaru.Parser.AST.Untyped
+ Language.Hakaru.Parser.AST: instance GHC.Show.Show a => GHC.Show.Show (Language.Hakaru.Parser.AST.AST' a)
+ Language.Hakaru.Parser.AST: instance GHC.Show.Show a => GHC.Show.Show (Language.Hakaru.Parser.AST.ASTWithImport' a)
+ Language.Hakaru.Parser.AST: instance GHC.Show.Show a => GHC.Show.Show (Language.Hakaru.Parser.AST.Branch' a)
+ Language.Hakaru.Parser.AST: instance GHC.Show.Show a => GHC.Show.Show (Language.Hakaru.Parser.AST.Import a)
+ Language.Hakaru.Parser.AST: instance GHC.Show.Show a => GHC.Show.Show (Language.Hakaru.Parser.AST.PDatum a)
+ Language.Hakaru.Parser.AST: instance GHC.Show.Show a => GHC.Show.Show (Language.Hakaru.Parser.AST.Pattern' a)
+ Language.Hakaru.Parser.AST: instance Language.Hakaru.Syntax.IClasses.Eq1 Language.Hakaru.Types.Sing.Sing
+ Language.Hakaru.Parser.AST: instance Language.Hakaru.Syntax.IClasses.Foldable21 Language.Hakaru.Parser.AST.Term
+ Language.Hakaru.Parser.AST: instance Language.Hakaru.Syntax.IClasses.Functor21 Language.Hakaru.Parser.AST.Term
+ Language.Hakaru.Parser.AST: instance Language.Hakaru.Syntax.IClasses.JmEq1 Language.Hakaru.Types.Sing.Sing
+ Language.Hakaru.Parser.AST: instance Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing
+ Language.Hakaru.Parser.AST: instance Language.Hakaru.Types.Sing.SingI 'Language.Hakaru.Parser.AST.U
+ Language.Hakaru.Parser.AST: nameID :: Name -> Nat
+ Language.Hakaru.Parser.AST: nameToVar :: Name -> Variable U
+ Language.Hakaru.Parser.AST: numberLine :: Text -> Int -> Text
+ Language.Hakaru.Parser.AST: printSourceSpan :: SourceSpan -> Vector Text -> Text
+ Language.Hakaru.Parser.AST: type AST = MetaABT SourceSpan Term '[] U
+ Language.Hakaru.Parser.AST: type Branch = Branch_ (MetaABT SourceSpan Term)
+ Language.Hakaru.Parser.AST: type DCode_ = DCode (MetaABT SourceSpan Term)
+ Language.Hakaru.Parser.AST: type DFun_ = DFun (MetaABT SourceSpan Term)
+ Language.Hakaru.Parser.AST: type DStruct_ = DStruct (MetaABT SourceSpan Term)
+ Language.Hakaru.Parser.AST: type MetaTerm = Term (MetaABT SourceSpan Term) U
+ Language.Hakaru.Parser.AST: type Name' = Text
+ Language.Hakaru.Parser.AST: val :: Literal' -> Some1 Literal
+ Language.Hakaru.Parser.Maple: And_ :: ArgOp
+ Language.Hakaru.Parser.Maple: Equal :: ArgOp
+ Language.Hakaru.Parser.Maple: ExpSeq :: ArgOp
+ Language.Hakaru.Parser.Maple: Float :: ArgOp
+ Language.Hakaru.Parser.Maple: Func :: ArgOp
+ Language.Hakaru.Parser.Maple: InertArgs :: ArgOp -> [InertExpr] -> InertExpr
+ Language.Hakaru.Parser.Maple: InertName :: Text -> InertExpr
+ Language.Hakaru.Parser.Maple: InertNum :: NumOp -> Integer -> InertExpr
+ Language.Hakaru.Parser.Maple: Less :: ArgOp
+ Language.Hakaru.Parser.Maple: List :: ArgOp
+ Language.Hakaru.Parser.Maple: Neg :: NumOp
+ Language.Hakaru.Parser.Maple: NotEq :: ArgOp
+ Language.Hakaru.Parser.Maple: Not_ :: ArgOp
+ Language.Hakaru.Parser.Maple: Pos :: NumOp
+ Language.Hakaru.Parser.Maple: Power :: ArgOp
+ Language.Hakaru.Parser.Maple: Prod_ :: ArgOp
+ Language.Hakaru.Parser.Maple: Range :: ArgOp
+ Language.Hakaru.Parser.Maple: Rational :: ArgOp
+ Language.Hakaru.Parser.Maple: Sum_ :: ArgOp
+ Language.Hakaru.Parser.Maple: and :: Parser InertExpr
+ Language.Hakaru.Parser.Maple: arg :: Parser a -> Parser [a]
+ Language.Hakaru.Parser.Maple: assignedlocalname :: Parser InertExpr
+ Language.Hakaru.Parser.Maple: assignedname :: Parser InertExpr
+ Language.Hakaru.Parser.Maple: branch :: InertExpr -> Branch' Text
+ Language.Hakaru.Parser.Maple: collapseNaryOp :: NaryOp -> [AST' Text] -> [AST' Text]
+ Language.Hakaru.Parser.Maple: comma :: Parser String
+ Language.Hakaru.Parser.Maple: commaSep :: Parser a -> Parser [a]
+ Language.Hakaru.Parser.Maple: data ArgOp
+ Language.Hakaru.Parser.Maple: data InertExpr
+ Language.Hakaru.Parser.Maple: data NumOp
+ Language.Hakaru.Parser.Maple: equal :: Parser InertExpr
+ Language.Hakaru.Parser.Maple: expr :: Parser InertExpr
+ Language.Hakaru.Parser.Maple: expseq :: Parser InertExpr
+ Language.Hakaru.Parser.Maple: float :: Parser InertExpr
+ Language.Hakaru.Parser.Maple: func :: Parser InertExpr
+ Language.Hakaru.Parser.Maple: identifier :: Parser Text
+ Language.Hakaru.Parser.Maple: instance GHC.Classes.Eq Language.Hakaru.Parser.Maple.ArgOp
+ Language.Hakaru.Parser.Maple: instance GHC.Classes.Eq Language.Hakaru.Parser.Maple.InertExpr
+ Language.Hakaru.Parser.Maple: instance GHC.Classes.Eq Language.Hakaru.Parser.Maple.NumOp
+ Language.Hakaru.Parser.Maple: instance GHC.Show.Show Language.Hakaru.Parser.Maple.ArgOp
+ Language.Hakaru.Parser.Maple: instance GHC.Show.Show Language.Hakaru.Parser.Maple.InertExpr
+ Language.Hakaru.Parser.Maple: instance GHC.Show.Show Language.Hakaru.Parser.Maple.NumOp
+ Language.Hakaru.Parser.Maple: integer :: Parser Integer
+ Language.Hakaru.Parser.Maple: intneg :: Parser InertExpr
+ Language.Hakaru.Parser.Maple: intpos :: Parser InertExpr
+ Language.Hakaru.Parser.Maple: lesseq :: Parser InertExpr
+ Language.Hakaru.Parser.Maple: lessthan :: Parser InertExpr
+ Language.Hakaru.Parser.Maple: lexer :: TokenParser ()
+ Language.Hakaru.Parser.Maple: list :: Parser InertExpr
+ Language.Hakaru.Parser.Maple: maple2AST :: InertExpr -> AST' Text
+ Language.Hakaru.Parser.Maple: maple2DCode :: InertExpr -> [AST' Text]
+ Language.Hakaru.Parser.Maple: maple2Pattern :: InertExpr -> Pattern' Text
+ Language.Hakaru.Parser.Maple: maple2Patterns :: InertExpr -> [Pattern' Text]
+ Language.Hakaru.Parser.Maple: maple2Type :: InertExpr -> TypeAST'
+ Language.Hakaru.Parser.Maple: mapleDatum2AST :: Text -> InertExpr -> AST' Text
+ Language.Hakaru.Parser.Maple: name :: Parser InertExpr
+ Language.Hakaru.Parser.Maple: not :: Parser InertExpr
+ Language.Hakaru.Parser.Maple: noteq :: Parser InertExpr
+ Language.Hakaru.Parser.Maple: parens :: Parser a -> Parser a
+ Language.Hakaru.Parser.Maple: parseMaple :: Text -> Either ParseError InertExpr
+ Language.Hakaru.Parser.Maple: power :: Parser InertExpr
+ Language.Hakaru.Parser.Maple: product :: Parser InertExpr
+ Language.Hakaru.Parser.Maple: range :: Parser InertExpr
+ Language.Hakaru.Parser.Maple: rational :: Parser InertExpr
+ Language.Hakaru.Parser.Maple: rename :: Text -> Text
+ Language.Hakaru.Parser.Maple: stringLiteral :: Parser Text
+ Language.Hakaru.Parser.Maple: style :: GenLanguageDef Text st Identity
+ Language.Hakaru.Parser.Maple: sum :: Parser InertExpr
+ Language.Hakaru.Parser.Maple: symTable :: [(Text, Text)]
+ Language.Hakaru.Parser.Maple: text :: Text -> Parser Text
+ Language.Hakaru.Parser.Maple: type TokenParser a = GenTokenParser Text a Identity
+ Language.Hakaru.Parser.Parser: ann_expr :: Parser (AST' Text -> AST' Text)
+ Language.Hakaru.Parser.Parser: app1 :: Text -> AST' Text -> AST' Text
+ Language.Hakaru.Parser.Parser: app2 :: Text -> AST' Text -> AST' Text -> AST' Text
+ Language.Hakaru.Parser.Parser: array_expr :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: array_index :: Parser (AST' Text -> AST' Text)
+ Language.Hakaru.Parser.Parser: array_literal :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: binary :: String -> Assoc -> Operator (AST' Text)
+ Language.Hakaru.Parser.Parser: bind_expr :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: binop :: Text -> AST' Text -> AST' Text -> AST' Text
+ Language.Hakaru.Parser.Parser: blockOfMany :: Parser a -> Parser [a]
+ Language.Hakaru.Parser.Parser: braces :: Parser a -> Parser a
+ Language.Hakaru.Parser.Parser: brackets :: Parser a -> Parser a
+ Language.Hakaru.Parser.Parser: branch_expr :: Parser (Branch' Text)
+ Language.Hakaru.Parser.Parser: call_expr :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: chain_expr :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: commaSep :: Parser a -> Parser [a]
+ Language.Hakaru.Parser.Parser: comments :: Parser ()
+ Language.Hakaru.Parser.Parser: data_expr :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: decimal :: Parser Integer
+ Language.Hakaru.Parser.Parser: def_expr :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: defarg :: Parser (Text, TypeAST')
+ Language.Hakaru.Parser.Parser: divide :: AST' Text -> AST' Text -> AST' Text
+ Language.Hakaru.Parser.Parser: emptyLine :: Parser ()
+ Language.Hakaru.Parser.Parser: empty_ :: Parser (AST' a)
+ Language.Hakaru.Parser.Parser: expect_expr :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: exponent' :: Parser Rational
+ Language.Hakaru.Parser.Parser: expr :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: exprWithImport :: Parser (ASTWithImport' Text)
+ Language.Hakaru.Parser.Parser: float :: Parser Rational
+ Language.Hakaru.Parser.Parser: floating :: Parser (AST' a)
+ Language.Hakaru.Parser.Parser: fractExponent :: Integer -> Parser Rational
+ Language.Hakaru.Parser.Parser: fractFloat :: Integer -> Parser (Either Integer Rational)
+ Language.Hakaru.Parser.Parser: fraction :: Parser Rational
+ Language.Hakaru.Parser.Parser: identifier :: Parser Text
+ Language.Hakaru.Parser.Parser: if_expr :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: import_expr :: Parser (Import Text)
+ Language.Hakaru.Parser.Parser: indentConfig :: Text -> ParserStream
+ Language.Hakaru.Parser.Parser: inf_ :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: int :: Parser (AST' a)
+ Language.Hakaru.Parser.Parser: integer :: Parser Integer
+ Language.Hakaru.Parser.Parser: integrate_expr :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: lam_expr :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: let_expr :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: lexer :: GenTokenParser ParserStream () Identity
+ Language.Hakaru.Parser.Parser: match_expr :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: names :: [String]
+ Language.Hakaru.Parser.Parser: observe_expr :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: ops :: [String]
+ Language.Hakaru.Parser.Parser: pairs :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: parens :: Parser a -> Parser a
+ Language.Hakaru.Parser.Parser: parseHakaru :: Text -> Either ParseError (AST' Text)
+ Language.Hakaru.Parser.Parser: parseHakaruWithImports :: Text -> Either ParseError (ASTWithImport' Text)
+ Language.Hakaru.Parser.Parser: pat_expr :: Parser (Pattern' Text)
+ Language.Hakaru.Parser.Parser: pdat_expr :: Parser (PDatum Text)
+ Language.Hakaru.Parser.Parser: plate_expr :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: postfix :: Parser (a -> a) -> Operator a
+ Language.Hakaru.Parser.Parser: prefix :: String -> (a -> a) -> Operator a
+ Language.Hakaru.Parser.Parser: product_expr :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: pseudoblockExpr :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: reserved :: String -> Parser ()
+ Language.Hakaru.Parser.Parser: reservedOp :: String -> Parser ()
+ Language.Hakaru.Parser.Parser: return_expr :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: semiSep :: Parser a -> Parser [a]
+ Language.Hakaru.Parser.Parser: semiSep1 :: Parser a -> Parser [a]
+ Language.Hakaru.Parser.Parser: semiblockExpr :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: style :: GenLanguageDef ParserStream st Identity
+ Language.Hakaru.Parser.Parser: summate_expr :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: symbol :: Text -> Parser Text
+ Language.Hakaru.Parser.Parser: table :: OperatorTable (AST' Text)
+ Language.Hakaru.Parser.Parser: term :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: type Operator a = Operator ParserStream () Identity a
+ Language.Hakaru.Parser.Parser: type OperatorTable a = [[Operator a]]
+ Language.Hakaru.Parser.Parser: type Parser = ParsecT ParserStream () Identity
+ Language.Hakaru.Parser.Parser: type ParserStream = IndentStream (CharIndentStream Text)
+ Language.Hakaru.Parser.Parser: type_app :: Parser TypeAST'
+ Language.Hakaru.Parser.Parser: type_expr :: Parser TypeAST'
+ Language.Hakaru.Parser.Parser: type_fun :: Parser TypeAST'
+ Language.Hakaru.Parser.Parser: type_var :: Parser TypeAST'
+ Language.Hakaru.Parser.Parser: types :: [String]
+ Language.Hakaru.Parser.Parser: unit_ :: Parser (AST' a)
+ Language.Hakaru.Parser.Parser: var :: Parser (AST' Text)
+ Language.Hakaru.Parser.Parser: whiteSpace :: Parser ()
+ Language.Hakaru.Parser.Parser: withPos :: Parser (AST' a) -> Parser (AST' a)
+ Language.Hakaru.Parser.SymbolResolve: TLam :: (a -> Symbol a) -> Symbol a
+ Language.Hakaru.Parser.SymbolResolve: TLam' :: ([a] -> a) -> Symbol' a
+ Language.Hakaru.Parser.SymbolResolve: TNeu :: a -> Symbol a
+ Language.Hakaru.Parser.SymbolResolve: TNeu' :: a -> Symbol' a
+ Language.Hakaru.Parser.SymbolResolve: branchNorm :: Branch' (Symbol AST) -> Branch' (Symbol AST)
+ Language.Hakaru.Parser.SymbolResolve: cInt2Real :: Coercion HInt HReal
+ Language.Hakaru.Parser.SymbolResolve: cNat2Int :: Coercion HNat HInt
+ Language.Hakaru.Parser.SymbolResolve: cNat2Prob :: Coercion HNat HProb
+ Language.Hakaru.Parser.SymbolResolve: cNat2Real :: Coercion HNat HReal
+ Language.Hakaru.Parser.SymbolResolve: cProb2Real :: Coercion HProb HReal
+ Language.Hakaru.Parser.SymbolResolve: collapseSuperposes :: [AST] -> AST
+ Language.Hakaru.Parser.SymbolResolve: data Symbol a
+ Language.Hakaru.Parser.SymbolResolve: data Symbol' a
+ Language.Hakaru.Parser.SymbolResolve: false_ :: AST
+ Language.Hakaru.Parser.SymbolResolve: fromVarSet :: VarSet (KProxy :: KProxy Hakaru) -> [Name]
+ Language.Hakaru.Parser.SymbolResolve: gensym :: Text -> State Int Name
+ Language.Hakaru.Parser.SymbolResolve: insertSymbol :: Name -> SymbolTable -> SymbolTable
+ Language.Hakaru.Parser.SymbolResolve: insertSymbols :: [Name] -> SymbolTable -> SymbolTable
+ Language.Hakaru.Parser.SymbolResolve: makeAST :: AST' (Symbol AST) -> AST
+ Language.Hakaru.Parser.SymbolResolve: makeBranch :: Branch' (Symbol AST) -> Branch
+ Language.Hakaru.Parser.SymbolResolve: makeFalse :: AST' (Symbol AST) -> Branch
+ Language.Hakaru.Parser.SymbolResolve: makeName :: SomeVariable (KProxy :: KProxy Hakaru) -> Name
+ Language.Hakaru.Parser.SymbolResolve: makePattern :: Pattern' Name -> Pattern
+ Language.Hakaru.Parser.SymbolResolve: makeTrue :: AST' (Symbol AST) -> Branch
+ Language.Hakaru.Parser.SymbolResolve: makeType :: TypeAST' -> SSing
+ Language.Hakaru.Parser.SymbolResolve: mkSym :: Name -> Symbol AST
+ Language.Hakaru.Parser.SymbolResolve: normAST :: AST' (Symbol AST) -> AST' (Symbol AST)
+ Language.Hakaru.Parser.SymbolResolve: pairPat :: Pattern -> Pattern -> Pattern
+ Language.Hakaru.Parser.SymbolResolve: primBern :: Symbol AST
+ Language.Hakaru.Parser.SymbolResolve: primCoerce :: Coercion a b -> Symbol AST
+ Language.Hakaru.Parser.SymbolResolve: primFactor :: Symbol AST
+ Language.Hakaru.Parser.SymbolResolve: primJust :: Symbol AST
+ Language.Hakaru.Parser.SymbolResolve: primLeft :: Symbol AST
+ Language.Hakaru.Parser.SymbolResolve: primMeasure1 :: SomeOp MeasureOp -> Symbol AST
+ Language.Hakaru.Parser.SymbolResolve: primMeasure2 :: SomeOp MeasureOp -> Symbol AST
+ Language.Hakaru.Parser.SymbolResolve: primNothing :: Symbol AST
+ Language.Hakaru.Parser.SymbolResolve: primPat :: [(Text, Symbol' Pattern)]
+ Language.Hakaru.Parser.SymbolResolve: primPrimOp0 :: PrimOp -> Symbol AST
+ Language.Hakaru.Parser.SymbolResolve: primPrimOp1 :: PrimOp -> Symbol AST
+ Language.Hakaru.Parser.SymbolResolve: primPrimOp2 :: PrimOp -> Symbol AST
+ Language.Hakaru.Parser.SymbolResolve: primRight :: Symbol AST
+ Language.Hakaru.Parser.SymbolResolve: primTable :: SymbolTable
+ Language.Hakaru.Parser.SymbolResolve: primTypes :: [(Text, Symbol' SSing)]
+ Language.Hakaru.Parser.SymbolResolve: primUnsafe :: Coercion a b -> Symbol AST
+ Language.Hakaru.Parser.SymbolResolve: primWeight :: Symbol AST
+ Language.Hakaru.Parser.SymbolResolve: resolveAST :: AST' Text -> AST
+ Language.Hakaru.Parser.SymbolResolve: resolveAST' :: [Name] -> AST' Text -> AST
+ Language.Hakaru.Parser.SymbolResolve: resolveBinder :: SymbolTable -> Text -> AST' Text -> AST' Text -> (Symbol AST -> AST' (Symbol AST) -> AST' (Symbol AST) -> AST' (Symbol AST)) -> State Int (AST' (Symbol AST))
+ Language.Hakaru.Parser.SymbolResolve: singleton :: a -> NonEmpty a
+ Language.Hakaru.Parser.SymbolResolve: symbolResolution :: SymbolTable -> AST' Text -> State Int (AST' (Symbol AST))
+ Language.Hakaru.Parser.SymbolResolve: symbolResolveBranch :: SymbolTable -> Branch' Text -> State Int (Branch' (Symbol AST))
+ Language.Hakaru.Parser.SymbolResolve: symbolResolvePat :: Pattern' Text -> State Int (Pattern' Name, [Name])
+ Language.Hakaru.Parser.SymbolResolve: t2 :: (AST -> AST -> AST) -> Symbol AST
+ Language.Hakaru.Parser.SymbolResolve: t3 :: (AST -> AST -> AST -> AST) -> Symbol AST
+ Language.Hakaru.Parser.SymbolResolve: true_ :: AST
+ Language.Hakaru.Parser.SymbolResolve: two :: AST
+ Language.Hakaru.Parser.SymbolResolve: type SymbolTable = [(Text, Symbol AST)]
+ Language.Hakaru.Parser.SymbolResolve: unit_ :: AST
+ Language.Hakaru.Parser.SymbolResolve: unsafeFrom_ :: AST -> AST
+ Language.Hakaru.Pretty.Concrete: instance Language.Hakaru.Pretty.Concrete.Pretty Language.Hakaru.Syntax.AST.Literal
+ Language.Hakaru.Pretty.Concrete: instance Language.Hakaru.Pretty.Concrete.Pretty Language.Hakaru.Syntax.Value.Value
+ Language.Hakaru.Pretty.Concrete: instance Language.Hakaru.Pretty.Concrete.Pretty f => Language.Hakaru.Pretty.Concrete.Pretty (Language.Hakaru.Syntax.Datum.Datum f)
+ Language.Hakaru.Pretty.Concrete: instance Language.Hakaru.Syntax.ABT.ABT Language.Hakaru.Syntax.AST.Term abt => Language.Hakaru.Pretty.Concrete.Pretty (Language.Hakaru.Syntax.AST.LC_ abt)
+ Language.Hakaru.Pretty.Concrete: instance Language.Hakaru.Syntax.ABT.ABT Language.Hakaru.Syntax.AST.Term abt => Language.Hakaru.Pretty.Concrete.Pretty (Language.Hakaru.Syntax.Datum.Branch a abt)
+ Language.Hakaru.Pretty.Concrete: pretty :: (ABT Term abt) => abt '[] a -> Doc
+ Language.Hakaru.Pretty.Concrete: prettyAssoc :: (ABT Term abt) => Assoc (abt '[]) -> Doc
+ Language.Hakaru.Pretty.Concrete: prettyPrec :: (ABT Term abt) => Int -> abt '[] a -> Doc
+ Language.Hakaru.Pretty.Concrete: prettyPrecAssoc :: (ABT Term abt) => Int -> Assoc (abt '[]) -> Doc
+ Language.Hakaru.Pretty.Concrete: prettyType :: Int -> Sing (a :: Hakaru) -> Doc
+ Language.Hakaru.Pretty.Concrete: prettyValue :: Value a -> Doc
+ Language.Hakaru.Pretty.Haskell: LeftAssoc :: Associativity
+ Language.Hakaru.Pretty.Haskell: NonAssoc :: Associativity
+ Language.Hakaru.Pretty.Haskell: RightAssoc :: Associativity
+ Language.Hakaru.Pretty.Haskell: class Pretty (f :: Hakaru -> *)
+ Language.Hakaru.Pretty.Haskell: data Associativity
+ Language.Hakaru.Pretty.Haskell: instance Language.Hakaru.Pretty.Haskell.Pretty (Language.Hakaru.Syntax.Datum.Pattern xs)
+ Language.Hakaru.Pretty.Haskell: instance Language.Hakaru.Pretty.Haskell.Pretty Language.Hakaru.Syntax.AST.Literal
+ Language.Hakaru.Pretty.Haskell: instance Language.Hakaru.Pretty.Haskell.Pretty f => Language.Hakaru.Pretty.Haskell.Pretty (Language.Hakaru.Syntax.Datum.Datum f)
+ Language.Hakaru.Pretty.Haskell: instance Language.Hakaru.Syntax.ABT.ABT Language.Hakaru.Syntax.AST.Term abt => Language.Hakaru.Pretty.Haskell.Pretty (Language.Hakaru.Syntax.AST.LC_ abt)
+ Language.Hakaru.Pretty.Haskell: instance Language.Hakaru.Syntax.ABT.ABT Language.Hakaru.Syntax.AST.Term abt => Language.Hakaru.Pretty.Haskell.Pretty (Language.Hakaru.Syntax.Datum.Branch a abt)
+ Language.Hakaru.Pretty.Haskell: ppBinder :: (ABT Term abt) => abt xs a -> Docs
+ Language.Hakaru.Pretty.Haskell: ppBinop :: (ABT Term abt) => String -> Int -> Associativity -> Int -> abt '[] a -> abt '[] b -> Docs
+ Language.Hakaru.Pretty.Haskell: ppCoerceTo :: ABT Term abt => Int -> Coercion a b -> abt '[] a -> Docs
+ Language.Hakaru.Pretty.Haskell: ppRatio :: (Show a, Integral a) => Int -> Ratio a -> Doc
+ Language.Hakaru.Pretty.Haskell: ppUnsafeFrom :: ABT Term abt => Int -> Coercion a b -> abt '[] b -> Docs
+ Language.Hakaru.Pretty.Haskell: ppVariable :: Variable (a :: Hakaru) -> Doc
+ Language.Hakaru.Pretty.Haskell: ppVariables :: List1 Variable (xs :: [Hakaru]) -> Docs
+ Language.Hakaru.Pretty.Haskell: pretty :: (ABT Term abt) => abt '[] a -> Doc
+ Language.Hakaru.Pretty.Haskell: prettyAssoc :: (ABT Term abt) => Assoc (abt '[]) -> Doc
+ Language.Hakaru.Pretty.Haskell: prettyPrec :: (ABT Term abt) => Int -> abt '[] a -> Doc
+ Language.Hakaru.Pretty.Haskell: prettyPrecAssoc :: (ABT Term abt) => Int -> Assoc (abt '[]) -> Doc
+ Language.Hakaru.Pretty.Haskell: prettyPrec_ :: Pretty f => Int -> f a -> Docs
+ Language.Hakaru.Pretty.Maple: mapleType :: Sing (a :: Hakaru) -> ShowS
+ Language.Hakaru.Pretty.Maple: pretty :: (ABT Term abt) => abt '[] a -> String
+ Language.Hakaru.Runtime.Prelude: (!) :: (Vector (MayBoxVec a) a) => MayBoxVec a a -> Int -> a
+ Language.Hakaru.Runtime.Prelude: Branch :: (a -> Maybe b) -> Branch a b
+ Language.Hakaru.Runtime.Prelude: Measure :: (GenIO -> IO (Maybe a)) -> Measure a
+ Language.Hakaru.Runtime.Prelude: PVar :: Pattern
+ Language.Hakaru.Runtime.Prelude: PWild :: Pattern
+ Language.Hakaru.Runtime.Prelude: [extract] :: Branch a b -> a -> Maybe b
+ Language.Hakaru.Runtime.Prelude: [unMeasure] :: Measure a -> GenIO -> IO (Maybe a)
+ Language.Hakaru.Runtime.Prelude: abs_ :: Num a => a -> a
+ Language.Hakaru.Runtime.Prelude: ann_ :: a -> b -> b
+ Language.Hakaru.Runtime.Prelude: app :: (a -> b) -> a -> b
+ Language.Hakaru.Runtime.Prelude: array :: (Vector (MayBoxVec a) a) => Int -> (Int -> a) -> MayBoxVec a a
+ Language.Hakaru.Runtime.Prelude: beta :: Double -> Double -> Measure Double
+ Language.Hakaru.Runtime.Prelude: branch :: (c -> Branch a b) -> c -> Branch a b
+ Language.Hakaru.Runtime.Prelude: case_ :: a -> [Branch a b] -> b
+ Language.Hakaru.Runtime.Prelude: categorical :: MayBoxVec Double Double -> Measure Int
+ Language.Hakaru.Runtime.Prelude: data Pattern
+ Language.Hakaru.Runtime.Prelude: dirac :: a -> Measure a
+ Language.Hakaru.Runtime.Prelude: extractBool :: Bool -> a -> Bool -> Maybe a
+ Language.Hakaru.Runtime.Prelude: false :: Bool
+ Language.Hakaru.Runtime.Prelude: fromInt :: Int -> Double
+ Language.Hakaru.Runtime.Prelude: fromProb :: Double -> Double
+ Language.Hakaru.Runtime.Prelude: gamma :: Double -> Double -> Measure Double
+ Language.Hakaru.Runtime.Prelude: infinity :: Double
+ Language.Hakaru.Runtime.Prelude: instance GHC.Base.Applicative Language.Hakaru.Runtime.Prelude.Measure
+ Language.Hakaru.Runtime.Prelude: instance GHC.Base.Functor Language.Hakaru.Runtime.Prelude.Measure
+ Language.Hakaru.Runtime.Prelude: instance GHC.Base.Monad Language.Hakaru.Runtime.Prelude.Measure
+ Language.Hakaru.Runtime.Prelude: int_ :: Int -> Int
+ Language.Hakaru.Runtime.Prelude: iterateM_ :: Monad m => (a -> m a) -> a -> m b
+ Language.Hakaru.Runtime.Prelude: lam :: (a -> b) -> a -> b
+ Language.Hakaru.Runtime.Prelude: let_ :: a -> (a -> b) -> b
+ Language.Hakaru.Runtime.Prelude: makeMeasure :: (GenIO -> IO a) -> Measure a
+ Language.Hakaru.Runtime.Prelude: nat2int :: Int -> Int
+ Language.Hakaru.Runtime.Prelude: nat2prob :: Int -> Double
+ Language.Hakaru.Runtime.Prelude: nat2real :: Int -> Double
+ Language.Hakaru.Runtime.Prelude: nat_ :: Int -> Int
+ Language.Hakaru.Runtime.Prelude: newtype Branch a b
+ Language.Hakaru.Runtime.Prelude: newtype Measure a
+ Language.Hakaru.Runtime.Prelude: normal :: Double -> Double -> Measure Double
+ Language.Hakaru.Runtime.Prelude: pair :: a -> b -> (a, b)
+ Language.Hakaru.Runtime.Prelude: pfalse :: a -> Branch Bool a
+ Language.Hakaru.Runtime.Prelude: plate :: (Vector (MayBoxVec a) a) => Int -> (Int -> Measure a) -> Measure (MayBoxVec a a)
+ Language.Hakaru.Runtime.Prelude: pose :: Double -> Measure a -> Measure a
+ Language.Hakaru.Runtime.Prelude: ppair :: Pattern -> Pattern -> (x -> y -> b) -> Branch (x, y) b
+ Language.Hakaru.Runtime.Prelude: prob_ :: NonNegativeRational -> Double
+ Language.Hakaru.Runtime.Prelude: product :: Num a => Int -> Int -> (Int -> a) -> a
+ Language.Hakaru.Runtime.Prelude: ptrue :: a -> Branch Bool a
+ Language.Hakaru.Runtime.Prelude: real_ :: Rational -> Double
+ Language.Hakaru.Runtime.Prelude: reject :: Measure a
+ Language.Hakaru.Runtime.Prelude: run :: Show a => GenIO -> Measure a -> IO ()
+ Language.Hakaru.Runtime.Prelude: size :: (Vector (MayBoxVec a) a) => MayBoxVec a a -> Int
+ Language.Hakaru.Runtime.Prelude: summate :: Num a => Int -> Int -> (Int -> a) -> a
+ Language.Hakaru.Runtime.Prelude: superpose :: [(Double, Measure a)] -> Measure a
+ Language.Hakaru.Runtime.Prelude: thRootOf :: Int -> Double -> Double
+ Language.Hakaru.Runtime.Prelude: true :: Bool
+ Language.Hakaru.Runtime.Prelude: uniform :: Double -> Double -> Measure Double
+ Language.Hakaru.Runtime.Prelude: unit :: ()
+ Language.Hakaru.Runtime.Prelude: unsafeNat :: Int -> Int
+ Language.Hakaru.Runtime.Prelude: unsafeProb :: Double -> Double
+ Language.Hakaru.Runtime.Prelude: withPrint :: Show a => (a -> IO b) -> a -> IO b
+ Language.Hakaru.Sample: EAssoc :: {-# UNPACK #-} !(Variable a) -> !(Value a) -> EAssoc
+ Language.Hakaru.Sample: Env :: (IntMap EAssoc) -> Env
+ Language.Hakaru.Sample: data EAssoc
+ Language.Hakaru.Sample: emptyEnv :: Env
+ Language.Hakaru.Sample: evalOp :: NaryOp a -> Value a -> Value a -> Value a
+ Language.Hakaru.Sample: evaluate :: (ABT Term abt) => abt '[] a -> Env -> Value a
+ Language.Hakaru.Sample: evaluateArray :: (ABT Term abt) => (abt '[] HNat) -> (abt '[HNat] a) -> Env -> Value (HArray a)
+ Language.Hakaru.Sample: evaluateArrayOp :: (ABT Term abt, typs ~ UnLCs args, args ~ LCs typs) => ArrayOp typs a -> SArgs abt args -> Env -> Value a
+ Language.Hakaru.Sample: evaluateCase :: forall abt a b. (ABT Term abt) => abt '[] a -> [Branch a abt b] -> Env -> Value b
+ Language.Hakaru.Sample: evaluateDatum :: (ABT Term abt) => Datum (abt '[]) (HData' a) -> Env -> Value (HData' a)
+ Language.Hakaru.Sample: evaluateEmpty :: Value (HArray a)
+ Language.Hakaru.Sample: evaluateLiteral :: Literal a -> Value a
+ Language.Hakaru.Sample: evaluateMeasureOp :: (ABT Term abt, typs ~ UnLCs args, args ~ LCs typs) => MeasureOp typs a -> SArgs abt args -> Env -> Value (HMeasure a)
+ Language.Hakaru.Sample: evaluateNaryOp :: (ABT Term abt) => NaryOp a -> Seq (abt '[] a) -> Env -> Value a
+ Language.Hakaru.Sample: evaluatePrimOp :: (ABT Term abt, typs ~ UnLCs args, args ~ LCs typs) => PrimOp typs a -> SArgs abt args -> Env -> Value a
+ Language.Hakaru.Sample: evaluateSCon :: (ABT Term abt) => SCon args a -> SArgs abt args -> Env -> Value a
+ Language.Hakaru.Sample: evaluateSuperpose :: (ABT Term abt) => NonEmpty (abt '[] HProb, abt '[] (HMeasure a)) -> Env -> Value (HMeasure a)
+ Language.Hakaru.Sample: evaluateTerm :: (ABT Term abt) => Term abt a -> Env -> Value a
+ Language.Hakaru.Sample: evaluateVar :: Env -> Variable a -> Value a
+ Language.Hakaru.Sample: identityElement :: NaryOp a -> Value a
+ Language.Hakaru.Sample: lookupVar :: Variable a -> Env -> Maybe (Value a)
+ Language.Hakaru.Sample: mapEvaluate :: (ABT Term abt) => Seq (abt '[] a) -> Env -> Seq (Value a)
+ Language.Hakaru.Sample: newtype Env
+ Language.Hakaru.Sample: normalize :: [Value HProb] -> (LogFloat, Double, [Double])
+ Language.Hakaru.Sample: normalizeVector :: Value (HArray HProb) -> (LogFloat, Double, Vector Double)
+ Language.Hakaru.Sample: poisson_rng :: Double -> GenIO -> IO Int
+ Language.Hakaru.Sample: runEvaluate :: (ABT Term abt) => abt '[] a -> Value a
+ Language.Hakaru.Sample: updateEnv :: EAssoc -> Env -> Env
+ Language.Hakaru.Simplify: MapleException :: String -> String -> MapleException
+ Language.Hakaru.Simplify: data MapleException
+ Language.Hakaru.Simplify: instance GHC.Exception.Exception Language.Hakaru.Simplify.MapleException
+ Language.Hakaru.Simplify: instance GHC.Show.Show Language.Hakaru.Simplify.MapleException
+ Language.Hakaru.Simplify: simplify :: forall abt a. (ABT Term abt) => abt '[] a -> IO (abt '[] a)
+ Language.Hakaru.Simplify: simplifyDebug :: forall abt a. (ABT Term abt) => Bool -> abt '[] a -> IO (abt '[] a)
+ Language.Hakaru.Syntax.ABT: MetaABT :: !(Maybe meta) -> !(View (syn (MetaABT meta syn)) xs a) -> MetaABT
+ Language.Hakaru.Syntax.ABT: [Bind] :: {-# UNPACK #-} !(Variable a) -> !(View rec xs b) -> View rec (a : xs) b
+ Language.Hakaru.Syntax.ABT: [Syn] :: !(rec a) -> View rec '[] a
+ Language.Hakaru.Syntax.ABT: [Var] :: {-# UNPACK #-} !(Variable a) -> View rec '[] a
+ Language.Hakaru.Syntax.ABT: [getMetadata] :: MetaABT -> !(Maybe meta)
+ Language.Hakaru.Syntax.ABT: [metaView] :: MetaABT -> !(View (syn (MetaABT meta syn)) xs a)
+ Language.Hakaru.Syntax.ABT: bind :: ABT syn abt => Variable a -> abt xs b -> abt (a : xs) b
+ Language.Hakaru.Syntax.ABT: binder :: (ABT syn abt) => Text -> Sing a -> (abt '[] a -> abt xs b) -> abt (a : xs) b
+ Language.Hakaru.Syntax.ABT: binds :: (ABT syn abt) => List1 Variable xs -> abt ys b -> abt (xs ++ ys) b
+ Language.Hakaru.Syntax.ABT: binds_ :: (ABT syn abt) => List1 Variable xs -> abt '[] b -> abt xs b
+ Language.Hakaru.Syntax.ABT: caseBind :: ABT syn abt => abt (x : xs) a -> (Variable x -> abt xs a -> r) -> r
+ Language.Hakaru.Syntax.ABT: caseBinds :: (ABT syn abt) => abt xs a -> (List1 Variable xs, abt '[] a)
+ Language.Hakaru.Syntax.ABT: caseVarSyn :: (ABT syn abt) => abt '[] a -> (Variable a -> r) -> (syn abt a -> r) -> r
+ Language.Hakaru.Syntax.ABT: cataABT :: forall (abt :: [k] -> k -> *) (syn :: ([k] -> k -> *) -> k -> *) (r :: [k] -> k -> *). (ABT syn abt, Functor21 syn) => (forall a. Variable a -> r '[] a) -> (forall x xs a. Variable x -> r xs a -> r (x : xs) a) -> (forall a. syn r a -> r '[] a) -> forall xs a. abt xs a -> r xs a
+ Language.Hakaru.Syntax.ABT: class ABT (syn :: ([k] -> k -> *) -> k -> *) (abt :: [k] -> k -> *) | abt -> syn where nextFree = nextVarID . freeVars nextFreeOrBind e = nextFree e `max` nextBind e
+ Language.Hakaru.Syntax.ABT: data MemoizedABT (syn :: ([k] -> k -> *) -> k -> *) (xs :: [k]) (a :: k)
+ Language.Hakaru.Syntax.ABT: data MetaABT (meta :: *) (syn :: ([k] -> k -> *) -> k -> *) (xs :: [k]) (a :: k)
+ Language.Hakaru.Syntax.ABT: data TrivialABT (syn :: ([k] -> k -> *) -> k -> *) (xs :: [k]) (a :: k)
+ Language.Hakaru.Syntax.ABT: data View :: (k -> *) -> [k] -> k -> *
+ Language.Hakaru.Syntax.ABT: freeVars :: ABT syn abt => abt xs a -> VarSet (KindOf a)
+ Language.Hakaru.Syntax.ABT: instance Language.Hakaru.Syntax.IClasses.Functor12 Language.Hakaru.Syntax.ABT.View
+ Language.Hakaru.Syntax.ABT: instance forall k (rec :: k -> GHC.Types.*) (xs :: [k]) (a :: k). (Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Show1 rec) => GHC.Show.Show (Language.Hakaru.Syntax.ABT.View rec xs a)
+ Language.Hakaru.Syntax.ABT: instance forall k (rec :: k -> GHC.Types.*) (xs :: [k]). (Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Show1 rec) => Language.Hakaru.Syntax.IClasses.Show1 (Language.Hakaru.Syntax.ABT.View rec xs)
+ Language.Hakaru.Syntax.ABT: instance forall k (rec :: k -> GHC.Types.*). (Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Show1 rec) => Language.Hakaru.Syntax.IClasses.Show2 (Language.Hakaru.Syntax.ABT.View rec)
+ Language.Hakaru.Syntax.ABT: instance forall k (syn :: ([k] -> k -> GHC.Types.*) -> k -> GHC.Types.*) (xs :: [k]) (a :: k). (Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Show1 (syn (Language.Hakaru.Syntax.ABT.MemoizedABT syn))) => GHC.Show.Show (Language.Hakaru.Syntax.ABT.MemoizedABT syn xs a)
+ Language.Hakaru.Syntax.ABT: instance forall k (syn :: ([k] -> k -> GHC.Types.*) -> k -> GHC.Types.*) (xs :: [k]) (a :: k). (Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Show1 (syn (Language.Hakaru.Syntax.ABT.TrivialABT syn))) => GHC.Show.Show (Language.Hakaru.Syntax.ABT.TrivialABT syn xs a)
+ Language.Hakaru.Syntax.ABT: instance forall k (syn :: ([k] -> k -> GHC.Types.*) -> k -> GHC.Types.*) (xs :: [k]). (Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Show1 (syn (Language.Hakaru.Syntax.ABT.MemoizedABT syn))) => Language.Hakaru.Syntax.IClasses.Show1 (Language.Hakaru.Syntax.ABT.MemoizedABT syn xs)
+ Language.Hakaru.Syntax.ABT: instance forall k (syn :: ([k] -> k -> GHC.Types.*) -> k -> GHC.Types.*) (xs :: [k]). (Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Show1 (syn (Language.Hakaru.Syntax.ABT.TrivialABT syn))) => Language.Hakaru.Syntax.IClasses.Show1 (Language.Hakaru.Syntax.ABT.TrivialABT syn xs)
+ Language.Hakaru.Syntax.ABT: instance forall k (syn :: ([k] -> k -> GHC.Types.*) -> k -> GHC.Types.*) meta (xs :: [k]) (a :: k). (Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Show1 (syn (Language.Hakaru.Syntax.ABT.MetaABT meta syn)), GHC.Show.Show meta) => GHC.Show.Show (Language.Hakaru.Syntax.ABT.MetaABT meta syn xs a)
+ Language.Hakaru.Syntax.ABT: instance forall k (syn :: ([k] -> k -> GHC.Types.*) -> k -> GHC.Types.*) meta (xs :: [k]). (Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Show1 (syn (Language.Hakaru.Syntax.ABT.MetaABT meta syn)), GHC.Show.Show meta) => Language.Hakaru.Syntax.IClasses.Show1 (Language.Hakaru.Syntax.ABT.MetaABT meta syn xs)
+ Language.Hakaru.Syntax.ABT: instance forall k (syn :: ([k] -> k -> GHC.Types.*) -> k -> GHC.Types.*) meta. (Language.Hakaru.Syntax.IClasses.JmEq1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Foldable21 syn) => Language.Hakaru.Syntax.ABT.ABT syn (Language.Hakaru.Syntax.ABT.MetaABT meta syn)
+ Language.Hakaru.Syntax.ABT: instance forall k (syn :: ([k] -> k -> GHC.Types.*) -> k -> GHC.Types.*) meta. (Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Show1 (syn (Language.Hakaru.Syntax.ABT.MetaABT meta syn)), GHC.Show.Show meta) => Language.Hakaru.Syntax.IClasses.Show2 (Language.Hakaru.Syntax.ABT.MetaABT meta syn)
+ Language.Hakaru.Syntax.ABT: instance forall k (syn :: ([k] -> k -> GHC.Types.*) -> k -> GHC.Types.*). (Language.Hakaru.Syntax.IClasses.JmEq1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Foldable21 syn) => Language.Hakaru.Syntax.ABT.ABT syn (Language.Hakaru.Syntax.ABT.MemoizedABT syn)
+ Language.Hakaru.Syntax.ABT: instance forall k (syn :: ([k] -> k -> GHC.Types.*) -> k -> GHC.Types.*). (Language.Hakaru.Syntax.IClasses.JmEq1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Foldable21 syn) => Language.Hakaru.Syntax.ABT.ABT syn (Language.Hakaru.Syntax.ABT.TrivialABT syn)
+ Language.Hakaru.Syntax.ABT: instance forall k (syn :: ([k] -> k -> GHC.Types.*) -> k -> GHC.Types.*). (Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Show1 (syn (Language.Hakaru.Syntax.ABT.MemoizedABT syn))) => Language.Hakaru.Syntax.IClasses.Show2 (Language.Hakaru.Syntax.ABT.MemoizedABT syn)
+ Language.Hakaru.Syntax.ABT: instance forall k (syn :: ([k] -> k -> GHC.Types.*) -> k -> GHC.Types.*). (Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Show1 (syn (Language.Hakaru.Syntax.ABT.TrivialABT syn))) => Language.Hakaru.Syntax.IClasses.Show2 (Language.Hakaru.Syntax.ABT.TrivialABT syn)
+ Language.Hakaru.Syntax.ABT: maxNextBind :: (ABT syn abt, Foldable f) => f (Some2 abt) -> Nat
+ Language.Hakaru.Syntax.ABT: maxNextFree :: (ABT syn abt, Foldable f) => f (Some2 abt) -> Nat
+ Language.Hakaru.Syntax.ABT: maxNextFreeOrBind :: (ABT syn abt, Foldable f) => f (Some2 abt) -> Nat
+ Language.Hakaru.Syntax.ABT: nextBind :: ABT syn abt => abt xs a -> Nat
+ Language.Hakaru.Syntax.ABT: nextFree :: ABT syn abt => abt xs a -> Nat
+ Language.Hakaru.Syntax.ABT: nextFreeOrBind :: ABT syn abt => abt xs a -> Nat
+ Language.Hakaru.Syntax.ABT: paraABT :: forall (abt :: [k] -> k -> *) (syn :: ([k] -> k -> *) -> k -> *) (r :: [k] -> k -> *). (ABT syn abt, Functor21 syn) => (forall a. Variable a -> r '[] a) -> (forall x xs a. Variable x -> abt xs a -> r xs a -> r (x : xs) a) -> (forall a. syn (Pair2 abt r) a -> r '[] a) -> forall xs a. abt xs a -> r xs a
+ Language.Hakaru.Syntax.ABT: rename :: forall syn abt (a :: k) xs (b :: k). (JmEq1 (Sing :: k -> *), Show1 (Sing :: k -> *), Functor21 syn, ABT syn abt) => Variable a -> Variable a -> abt xs b -> abt xs b
+ Language.Hakaru.Syntax.ABT: renames :: forall (syn :: ([k] -> k -> *) -> k -> *) (abt :: [k] -> k -> *) (xs :: [k]) (a :: k). (ABT syn abt, JmEq1 (Sing :: k -> *), Show1 (Sing :: k -> *), Functor21 syn) => Assocs (Variable :: k -> *) -> abt xs a -> abt xs a
+ Language.Hakaru.Syntax.ABT: resolveVar :: (JmEq1 (Sing :: k -> *), Show1 (Sing :: k -> *), ABT syn abt) => abt '[] (a :: k) -> Assocs (abt '[]) -> Either (Variable a) (syn abt a)
+ Language.Hakaru.Syntax.ABT: subst :: forall syn abt (a :: k) xs (b :: k). (JmEq1 (Sing :: k -> *), Show1 (Sing :: k -> *), Functor21 syn, ABT syn abt) => Variable a -> abt '[] a -> abt xs b -> abt xs b
+ Language.Hakaru.Syntax.ABT: substs :: forall (syn :: ([k] -> k -> *) -> k -> *) (abt :: [k] -> k -> *) (xs :: [k]) (a :: k). (ABT syn abt, JmEq1 (Sing :: k -> *), Show1 (Sing :: k -> *), Functor21 syn) => Assocs (abt '[]) -> abt xs a -> abt xs a
+ Language.Hakaru.Syntax.ABT: syn :: ABT syn abt => syn abt a -> abt '[] a
+ Language.Hakaru.Syntax.ABT: underBinders :: (ABT syn abt) => (abt '[] a -> abt '[] b) -> abt xs a -> abt xs b
+ Language.Hakaru.Syntax.ABT: unviewABT :: (ABT syn abt) => View (syn abt) xs a -> abt xs a
+ Language.Hakaru.Syntax.ABT: var :: ABT syn abt => Variable a -> abt '[] a
+ Language.Hakaru.Syntax.ABT: viewABT :: ABT syn abt => abt xs a -> View (syn abt) xs a
+ Language.Hakaru.Syntax.ABT: withMetadata :: meta -> MetaABT meta syn xs a -> MetaABT meta syn xs a
+ Language.Hakaru.Syntax.AST: LC_ :: abt '[] a -> LC_
+ Language.Hakaru.Syntax.AST: [:$] :: !(SCon args a) -> !(SArgs abt args) -> Term abt a
+ Language.Hakaru.Syntax.AST: [:*] :: !(abt vars a) -> !(SArgs abt args) -> SArgs abt ('(vars, a) : args)
+ Language.Hakaru.Syntax.AST: [Abs] :: !(HRing a) -> PrimOp '[a] (NonNegative a)
+ Language.Hakaru.Syntax.AST: [Acos] :: PrimOp '[HReal] HReal
+ Language.Hakaru.Syntax.AST: [Acosh] :: PrimOp '[HReal] HReal
+ Language.Hakaru.Syntax.AST: [And] :: NaryOp HBool
+ Language.Hakaru.Syntax.AST: [App_] :: SCon '[LC (a :-> b), LC a] b
+ Language.Hakaru.Syntax.AST: [ArrayOp_] :: (typs ~ UnLCs args, args ~ LCs typs) => !(ArrayOp typs a) -> SCon args a
+ Language.Hakaru.Syntax.AST: [Array_] :: !(abt '[] HNat) -> !(abt '[HNat] a) -> Term abt (HArray a)
+ Language.Hakaru.Syntax.AST: [Asin] :: PrimOp '[HReal] HReal
+ Language.Hakaru.Syntax.AST: [Asinh] :: PrimOp '[HReal] HReal
+ Language.Hakaru.Syntax.AST: [Atan] :: PrimOp '[HReal] HReal
+ Language.Hakaru.Syntax.AST: [Atanh] :: PrimOp '[HReal] HReal
+ Language.Hakaru.Syntax.AST: [BetaFunc] :: PrimOp '[HProb, HProb] HProb
+ Language.Hakaru.Syntax.AST: [Beta] :: MeasureOp '[HProb, HProb] HProb
+ Language.Hakaru.Syntax.AST: [Case_] :: !(abt '[] a) -> [Branch a abt b] -> Term abt b
+ Language.Hakaru.Syntax.AST: [Categorical] :: MeasureOp '[HArray HProb] HNat
+ Language.Hakaru.Syntax.AST: [Chain] :: SCon '[LC HNat, LC s, '('[s], HMeasure (HPair a s))] (HMeasure (HPair (HArray a) s))
+ Language.Hakaru.Syntax.AST: [CoerceTo_] :: !(Coercion a b) -> SCon '[LC a] b
+ Language.Hakaru.Syntax.AST: [Cos] :: PrimOp '[HReal] HReal
+ Language.Hakaru.Syntax.AST: [Cosh] :: PrimOp '[HReal] HReal
+ Language.Hakaru.Syntax.AST: [Counting] :: MeasureOp '[] HInt
+ Language.Hakaru.Syntax.AST: [Datum_] :: !(Datum (abt '[]) (HData' t)) -> Term abt (HData' t)
+ Language.Hakaru.Syntax.AST: [Diff] :: PrimOp '[HBool, HBool] HBool
+ Language.Hakaru.Syntax.AST: [Dirac] :: SCon '[LC a] (HMeasure a)
+ Language.Hakaru.Syntax.AST: [Empty_] :: !(Sing (HArray a)) -> Term abt (HArray a)
+ Language.Hakaru.Syntax.AST: [End] :: SArgs abt '[]
+ Language.Hakaru.Syntax.AST: [Equal] :: !(HEq a) -> PrimOp '[a, a] HBool
+ Language.Hakaru.Syntax.AST: [Erf] :: !(HContinuous a) -> PrimOp '[a] a
+ Language.Hakaru.Syntax.AST: [Exp] :: PrimOp '[HReal] HProb
+ Language.Hakaru.Syntax.AST: [Expect] :: SCon '[LC (HMeasure a), '('[a], HProb)] HProb
+ Language.Hakaru.Syntax.AST: [GammaFunc] :: PrimOp '[HReal] HProb
+ Language.Hakaru.Syntax.AST: [Gamma] :: MeasureOp '[HProb, HProb] HProb
+ Language.Hakaru.Syntax.AST: [Iff] :: NaryOp HBool
+ Language.Hakaru.Syntax.AST: [Impl] :: PrimOp '[HBool, HBool] HBool
+ Language.Hakaru.Syntax.AST: [Index] :: !(Sing a) -> ArrayOp '[HArray a, HNat] a
+ Language.Hakaru.Syntax.AST: [Infinity] :: HIntegrable a -> PrimOp '[] a
+ Language.Hakaru.Syntax.AST: [Integrate] :: SCon '[LC HReal, LC HReal, '('[HReal], HProb)] HProb
+ Language.Hakaru.Syntax.AST: [LInt] :: !Integer -> Literal HInt
+ Language.Hakaru.Syntax.AST: [LNat] :: !Natural -> Literal HNat
+ Language.Hakaru.Syntax.AST: [LProb] :: {-# UNPACK #-} !NonNegativeRational -> Literal HProb
+ Language.Hakaru.Syntax.AST: [LReal] :: {-# UNPACK #-} !Rational -> Literal HReal
+ Language.Hakaru.Syntax.AST: [Lam_] :: SCon '['('[a], b)] (a :-> b)
+ Language.Hakaru.Syntax.AST: [Lebesgue] :: MeasureOp '[] HReal
+ Language.Hakaru.Syntax.AST: [Less] :: !(HOrd a) -> PrimOp '[a, a] HBool
+ Language.Hakaru.Syntax.AST: [Let_] :: SCon '[LC a, '('[a], b)] b
+ Language.Hakaru.Syntax.AST: [Literal_] :: !(Literal a) -> Term abt a
+ Language.Hakaru.Syntax.AST: [Log] :: PrimOp '[HProb] HReal
+ Language.Hakaru.Syntax.AST: [MBind] :: SCon '[LC (HMeasure a), '('[a], HMeasure b)] (HMeasure b)
+ Language.Hakaru.Syntax.AST: [Max] :: !(HOrd a) -> NaryOp a
+ Language.Hakaru.Syntax.AST: [MeasureOp_] :: (typs ~ UnLCs args, args ~ LCs typs) => !(MeasureOp typs a) -> SCon args (HMeasure a)
+ Language.Hakaru.Syntax.AST: [Min] :: !(HOrd a) -> NaryOp a
+ Language.Hakaru.Syntax.AST: [Nand] :: PrimOp '[HBool, HBool] HBool
+ Language.Hakaru.Syntax.AST: [NaryOp_] :: !(NaryOp a) -> !(Seq (abt '[] a)) -> Term abt a
+ Language.Hakaru.Syntax.AST: [NatPow] :: !(HSemiring a) -> PrimOp '[a, HNat] a
+ Language.Hakaru.Syntax.AST: [NatRoot] :: !(HRadical a) -> PrimOp '[a, HNat] a
+ Language.Hakaru.Syntax.AST: [Negate] :: !(HRing a) -> PrimOp '[a] a
+ Language.Hakaru.Syntax.AST: [Nor] :: PrimOp '[HBool, HBool] HBool
+ Language.Hakaru.Syntax.AST: [Normal] :: MeasureOp '[HReal, HProb] HReal
+ Language.Hakaru.Syntax.AST: [Not] :: PrimOp '[HBool] HBool
+ Language.Hakaru.Syntax.AST: [Observe] :: SCon '[LC (HMeasure a), LC a] (HMeasure a)
+ Language.Hakaru.Syntax.AST: [Or] :: NaryOp HBool
+ Language.Hakaru.Syntax.AST: [Pi] :: PrimOp '[] HProb
+ Language.Hakaru.Syntax.AST: [Plate] :: SCon '[LC HNat, '('[HNat], HMeasure a)] (HMeasure (HArray a))
+ Language.Hakaru.Syntax.AST: [Poisson] :: MeasureOp '[HProb] HNat
+ Language.Hakaru.Syntax.AST: [PrimOp_] :: (typs ~ UnLCs args, args ~ LCs typs) => !(PrimOp typs a) -> SCon args a
+ Language.Hakaru.Syntax.AST: [Prod] :: !(HSemiring a) -> NaryOp a
+ Language.Hakaru.Syntax.AST: [Product] :: HDiscrete a -> HSemiring b -> SCon '[LC a, LC a, '('[a], b)] b
+ Language.Hakaru.Syntax.AST: [RealPow] :: PrimOp '[HProb, HReal] HProb
+ Language.Hakaru.Syntax.AST: [Recip] :: !(HFractional a) -> PrimOp '[a] a
+ Language.Hakaru.Syntax.AST: [Reduce] :: !(Sing a) -> ArrayOp '[a :-> (a :-> a), a, HArray a] a
+ Language.Hakaru.Syntax.AST: [Reject_] :: !(Sing (HMeasure a)) -> Term abt (HMeasure a)
+ Language.Hakaru.Syntax.AST: [Signum] :: !(HRing a) -> PrimOp '[a] a
+ Language.Hakaru.Syntax.AST: [Sin] :: PrimOp '[HReal] HReal
+ Language.Hakaru.Syntax.AST: [Sinh] :: PrimOp '[HReal] HReal
+ Language.Hakaru.Syntax.AST: [Size] :: !(Sing a) -> ArrayOp '[HArray a] HNat
+ Language.Hakaru.Syntax.AST: [Sum] :: !(HSemiring a) -> NaryOp a
+ Language.Hakaru.Syntax.AST: [Summate] :: HDiscrete a -> HSemiring b -> SCon '[LC a, LC a, '('[a], b)] b
+ Language.Hakaru.Syntax.AST: [Superpose_] :: NonEmpty (abt '[] HProb, abt '[] (HMeasure a)) -> Term abt (HMeasure a)
+ Language.Hakaru.Syntax.AST: [Tan] :: PrimOp '[HReal] HReal
+ Language.Hakaru.Syntax.AST: [Tanh] :: PrimOp '[HReal] HReal
+ Language.Hakaru.Syntax.AST: [Uniform] :: MeasureOp '[HReal, HReal] HReal
+ Language.Hakaru.Syntax.AST: [UnsafeFrom_] :: !(Coercion a b) -> SCon '[LC b] a
+ Language.Hakaru.Syntax.AST: [Xor] :: NaryOp HBool
+ Language.Hakaru.Syntax.AST: [unLC_] :: LC_ -> abt '[] a
+ Language.Hakaru.Syntax.AST: data ArrayOp :: [Hakaru] -> Hakaru -> *
+ Language.Hakaru.Syntax.AST: data Literal :: Hakaru -> *
+ Language.Hakaru.Syntax.AST: data MeasureOp :: [Hakaru] -> Hakaru -> *
+ Language.Hakaru.Syntax.AST: data NaryOp :: Hakaru -> *
+ Language.Hakaru.Syntax.AST: data PrimOp :: [Hakaru] -> Hakaru -> *
+ Language.Hakaru.Syntax.AST: data SArgs :: ([Hakaru] -> Hakaru -> *) -> [([Hakaru], Hakaru)] -> *
+ Language.Hakaru.Syntax.AST: data SCon :: [([Hakaru], Hakaru)] -> Hakaru -> *
+ Language.Hakaru.Syntax.AST: data Term :: ([Hakaru] -> Hakaru -> *) -> Hakaru -> *
+ Language.Hakaru.Syntax.AST: foldMapPairs :: (Monoid m, Foldable f) => (forall h i. abt h i -> m) -> f (abt xs a, abt ys b) -> m
+ Language.Hakaru.Syntax.AST: instance GHC.Classes.Eq (Language.Hakaru.Syntax.AST.ArrayOp args a)
+ Language.Hakaru.Syntax.AST: instance GHC.Classes.Eq (Language.Hakaru.Syntax.AST.Literal a)
+ Language.Hakaru.Syntax.AST: instance GHC.Classes.Eq (Language.Hakaru.Syntax.AST.MeasureOp typs a)
+ Language.Hakaru.Syntax.AST: instance GHC.Classes.Eq (Language.Hakaru.Syntax.AST.NaryOp a)
+ Language.Hakaru.Syntax.AST: instance GHC.Classes.Eq (Language.Hakaru.Syntax.AST.PrimOp args a)
+ Language.Hakaru.Syntax.AST: instance GHC.Classes.Eq (Language.Hakaru.Syntax.AST.SCon args a)
+ Language.Hakaru.Syntax.AST: instance GHC.Show.Show (Language.Hakaru.Syntax.AST.ArrayOp args a)
+ Language.Hakaru.Syntax.AST: instance GHC.Show.Show (Language.Hakaru.Syntax.AST.Literal a)
+ Language.Hakaru.Syntax.AST: instance GHC.Show.Show (Language.Hakaru.Syntax.AST.MeasureOp typs a)
+ Language.Hakaru.Syntax.AST: instance GHC.Show.Show (Language.Hakaru.Syntax.AST.NaryOp a)
+ Language.Hakaru.Syntax.AST: instance GHC.Show.Show (Language.Hakaru.Syntax.AST.PrimOp args a)
+ Language.Hakaru.Syntax.AST: instance GHC.Show.Show (Language.Hakaru.Syntax.AST.SCon args a)
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.ABT.ABT Language.Hakaru.Syntax.AST.Term abt => Language.Hakaru.Types.Coercion.Coerce (Language.Hakaru.Syntax.AST.LC_ abt)
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.ABT.ABT Language.Hakaru.Syntax.AST.Term abt => Language.Hakaru.Types.Coercion.Coerce (Language.Hakaru.Syntax.AST.Term abt)
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.Eq1 (Language.Hakaru.Syntax.AST.ArrayOp args)
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.Eq1 (Language.Hakaru.Syntax.AST.MeasureOp typs)
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.Eq1 (Language.Hakaru.Syntax.AST.PrimOp args)
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.Eq1 Language.Hakaru.Syntax.AST.Literal
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.Eq1 Language.Hakaru.Syntax.AST.NaryOp
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.Eq2 Language.Hakaru.Syntax.AST.ArrayOp
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.Eq2 Language.Hakaru.Syntax.AST.MeasureOp
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.Eq2 Language.Hakaru.Syntax.AST.PrimOp
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.Eq2 abt => GHC.Classes.Eq (Language.Hakaru.Syntax.AST.SArgs abt args)
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.Eq2 abt => Language.Hakaru.Syntax.IClasses.Eq1 (Language.Hakaru.Syntax.AST.SArgs abt)
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.Foldable21 Language.Hakaru.Syntax.AST.SArgs
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.Foldable21 Language.Hakaru.Syntax.AST.Term
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.Functor21 Language.Hakaru.Syntax.AST.SArgs
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.Functor21 Language.Hakaru.Syntax.AST.Term
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.JmEq1 Language.Hakaru.Syntax.AST.Literal
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.JmEq1 Language.Hakaru.Syntax.AST.NaryOp
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.JmEq2 Language.Hakaru.Syntax.AST.ArrayOp
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.JmEq2 Language.Hakaru.Syntax.AST.MeasureOp
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.JmEq2 Language.Hakaru.Syntax.AST.PrimOp
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Syntax.AST.Literal
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.Show2 abt => GHC.Show.Show (Language.Hakaru.Syntax.AST.SArgs abt args)
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.Show2 abt => GHC.Show.Show (Language.Hakaru.Syntax.AST.Term abt a)
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.Show2 abt => Language.Hakaru.Syntax.IClasses.Show1 (Language.Hakaru.Syntax.AST.LC_ abt)
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.Show2 abt => Language.Hakaru.Syntax.IClasses.Show1 (Language.Hakaru.Syntax.AST.SArgs abt)
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.Show2 abt => Language.Hakaru.Syntax.IClasses.Show1 (Language.Hakaru.Syntax.AST.Term abt)
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.Traversable21 Language.Hakaru.Syntax.AST.SArgs
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Syntax.IClasses.Traversable21 Language.Hakaru.Syntax.AST.Term
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Types.Coercion.Coerce Language.Hakaru.Syntax.AST.Literal
+ Language.Hakaru.Syntax.AST: instance Language.Hakaru.Types.Coercion.PrimCoerce Language.Hakaru.Syntax.AST.Literal
+ Language.Hakaru.Syntax.AST: newtype LC_ (abt :: [Hakaru] -> Hakaru -> *) (a :: Hakaru)
+ Language.Hakaru.Syntax.AST: traversePairs :: (Applicative f, Traversable t) => (forall h i. abt1 h i -> f (abt2 h i)) -> t (abt1 xs a, abt1 ys b) -> f (t (abt2 xs a, abt2 ys b))
+ Language.Hakaru.Syntax.AST: type LC (a :: Hakaru) = '('[], a)
+ Language.Hakaru.Syntax.AST.Eq: all_jmEq2 :: (ABT Term abt, JmEq2 abt) => Seq (abt '[] a) -> Seq (abt '[] a) -> Maybe ()
+ Language.Hakaru.Syntax.AST.Eq: alphaEq :: forall abt a. (ABT Term abt) => abt '[] a -> abt '[] a -> Bool
+ Language.Hakaru.Syntax.AST.Eq: instance (Language.Hakaru.Syntax.ABT.ABT Language.Hakaru.Syntax.AST.Term abt, Language.Hakaru.Syntax.IClasses.JmEq2 abt) => GHC.Classes.Eq (Language.Hakaru.Syntax.AST.Term abt a)
+ Language.Hakaru.Syntax.AST.Eq: instance (Language.Hakaru.Syntax.ABT.ABT Language.Hakaru.Syntax.AST.Term abt, Language.Hakaru.Syntax.IClasses.JmEq2 abt) => Language.Hakaru.Syntax.IClasses.Eq1 (Language.Hakaru.Syntax.AST.Term abt)
+ Language.Hakaru.Syntax.AST.Eq: instance (Language.Hakaru.Syntax.ABT.ABT Language.Hakaru.Syntax.AST.Term abt, Language.Hakaru.Syntax.IClasses.JmEq2 abt) => Language.Hakaru.Syntax.IClasses.JmEq1 (Language.Hakaru.Syntax.AST.Term abt)
+ Language.Hakaru.Syntax.AST.Eq: instance Language.Hakaru.Syntax.IClasses.JmEq2 abt => Language.Hakaru.Syntax.IClasses.JmEq1 (Language.Hakaru.Syntax.AST.SArgs abt)
+ Language.Hakaru.Syntax.AST.Eq: instance forall k (syn :: ([k] -> k -> GHC.Types.*) -> k -> GHC.Types.*) (xs :: [k]) (a :: k). (Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.JmEq1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Foldable21 syn, Language.Hakaru.Syntax.IClasses.JmEq1 (syn (Language.Hakaru.Syntax.ABT.TrivialABT syn))) => GHC.Classes.Eq (Language.Hakaru.Syntax.ABT.TrivialABT syn xs a)
+ Language.Hakaru.Syntax.AST.Eq: instance forall k (syn :: ([k] -> k -> GHC.Types.*) -> k -> GHC.Types.*) (xs :: [k]). (Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.JmEq1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Foldable21 syn, Language.Hakaru.Syntax.IClasses.JmEq1 (syn (Language.Hakaru.Syntax.ABT.TrivialABT syn))) => Language.Hakaru.Syntax.IClasses.Eq1 (Language.Hakaru.Syntax.ABT.TrivialABT syn xs)
+ Language.Hakaru.Syntax.AST.Eq: instance forall k (syn :: ([k] -> k -> GHC.Types.*) -> k -> GHC.Types.*) (xs :: [k]). (Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.JmEq1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.JmEq1 (syn (Language.Hakaru.Syntax.ABT.TrivialABT syn)), Language.Hakaru.Syntax.IClasses.Foldable21 syn) => Language.Hakaru.Syntax.IClasses.JmEq1 (Language.Hakaru.Syntax.ABT.TrivialABT syn xs)
+ Language.Hakaru.Syntax.AST.Eq: instance forall k (syn :: ([k] -> k -> GHC.Types.*) -> k -> GHC.Types.*). (Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.JmEq1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Foldable21 syn, Language.Hakaru.Syntax.IClasses.JmEq1 (syn (Language.Hakaru.Syntax.ABT.TrivialABT syn))) => Language.Hakaru.Syntax.IClasses.Eq2 (Language.Hakaru.Syntax.ABT.TrivialABT syn)
+ Language.Hakaru.Syntax.AST.Eq: instance forall k (syn :: ([k] -> k -> GHC.Types.*) -> k -> GHC.Types.*). (Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.JmEq1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.JmEq1 (syn (Language.Hakaru.Syntax.ABT.TrivialABT syn)), Language.Hakaru.Syntax.IClasses.Foldable21 syn) => Language.Hakaru.Syntax.IClasses.JmEq2 (Language.Hakaru.Syntax.ABT.TrivialABT syn)
+ Language.Hakaru.Syntax.AST.Eq: jmEq_Branch :: (ABT Term abt, JmEq2 abt) => [(Branch a abt b, Branch a abt b')] -> Maybe (TypeEq b b')
+ Language.Hakaru.Syntax.AST.Eq: jmEq_S :: (ABT Term abt, JmEq2 abt) => SCon args a -> SArgs abt args -> SCon args' a' -> SArgs abt args' -> Maybe (TypeEq a a', TypeEq args args')
+ Language.Hakaru.Syntax.AST.Eq: jmEq_Tuple :: (ABT Term abt, JmEq2 abt) => ((abt '[] a, abt '[] b), (abt '[] a', abt '[] b')) -> Maybe (TypeEq a a', TypeEq b b')
+ Language.Hakaru.Syntax.AST.Eq: try_bool :: Bool -> ReaderT Varmap Maybe ()
+ Language.Hakaru.Syntax.AST.Eq: type Varmap = Assocs (Variable :: Hakaru -> *)
+ Language.Hakaru.Syntax.AST.Eq: void_jmEq1 :: Sing (a :: Hakaru) -> Sing (b :: Hakaru) -> ReaderT Varmap Maybe ()
+ Language.Hakaru.Syntax.AST.Eq: void_varEq :: Variable (a :: Hakaru) -> Variable (b :: Hakaru) -> ReaderT Varmap Maybe ()
+ Language.Hakaru.Syntax.AST.Sing: sing_ArrayOp :: ArrayOp typs a -> (List1 Sing typs, Sing a)
+ Language.Hakaru.Syntax.AST.Sing: sing_Literal :: Literal a -> Sing a
+ Language.Hakaru.Syntax.AST.Sing: sing_MeasureOp :: MeasureOp typs a -> (List1 Sing typs, Sing a)
+ Language.Hakaru.Syntax.AST.Sing: sing_NaryOp :: NaryOp a -> Sing a
+ Language.Hakaru.Syntax.AST.Sing: sing_PrimOp :: PrimOp typs a -> (List1 Sing typs, Sing a)
+ Language.Hakaru.Syntax.AST.Transforms: coalesce :: forall abt a. (ABT Term abt) => abt '[] a -> abt '[] a
+ Language.Hakaru.Syntax.AST.Transforms: coalesceNaryOp :: ABT Term abt => NaryOp a -> Seq (abt '[] a) -> Seq (abt '[] a)
+ Language.Hakaru.Syntax.AST.Transforms: expandTransformations :: forall abt a. (ABT Term abt) => abt '[] a -> abt '[] a
+ Language.Hakaru.Syntax.AST.Transforms: underLam :: (ABT Term abt, Monad m) => (abt '[] b -> m (abt '[] b)) -> abt '[] (a :-> b) -> m (abt '[] (a :-> b))
+ Language.Hakaru.Syntax.Datum: Branch :: !(Pattern xs a) -> !(abt xs b) -> Branch
+ Language.Hakaru.Syntax.Datum: GBranch :: !(Pattern xs a) -> !(List1 Variable xs) -> r -> GBranch
+ Language.Hakaru.Syntax.Datum: [Datum] :: {-# UNPACK #-} !Text -> !(Sing (HData' t)) -> !(DatumCode (Code t) ast (HData' t)) -> Datum ast (HData' t)
+ Language.Hakaru.Syntax.Datum: [Done] :: DatumStruct '[] abt a
+ Language.Hakaru.Syntax.Datum: [Et] :: !(DatumFun x abt a) -> !(DatumStruct xs abt a) -> DatumStruct (x : xs) abt a
+ Language.Hakaru.Syntax.Datum: [Ident] :: !(ast a) -> DatumFun I ast a
+ Language.Hakaru.Syntax.Datum: [Inl] :: !(DatumStruct xs abt a) -> DatumCode (xs : xss) abt a
+ Language.Hakaru.Syntax.Datum: [Inr] :: !(DatumCode xss abt a) -> DatumCode (xs : xss) abt a
+ Language.Hakaru.Syntax.Datum: [Konst] :: !(ast b) -> DatumFun (K b) ast a
+ Language.Hakaru.Syntax.Datum: [PDatum] :: {-# UNPACK #-} !Text -> !(PDatumCode (Code t) vars (HData' t)) -> Pattern vars (HData' t)
+ Language.Hakaru.Syntax.Datum: [PDone] :: PDatumStruct '[] '[] a
+ Language.Hakaru.Syntax.Datum: [PEt] :: !(PDatumFun x vars1 a) -> !(PDatumStruct xs vars2 a) -> PDatumStruct (x : xs) (vars1 ++ vars2) a
+ Language.Hakaru.Syntax.Datum: [PIdent] :: !(Pattern vars a) -> PDatumFun I vars a
+ Language.Hakaru.Syntax.Datum: [PInl] :: !(PDatumStruct xs vars a) -> PDatumCode (xs : xss) vars a
+ Language.Hakaru.Syntax.Datum: [PInr] :: !(PDatumCode xss vars a) -> PDatumCode (xs : xss) vars a
+ Language.Hakaru.Syntax.Datum: [PKonst] :: !(Pattern vars b) -> PDatumFun (K b) vars a
+ Language.Hakaru.Syntax.Datum: [PVar] :: Pattern '[a] a
+ Language.Hakaru.Syntax.Datum: [PWild] :: Pattern '[] a
+ Language.Hakaru.Syntax.Datum: dCons :: (SingI a) => ast a -> ast (HList a) -> Datum ast (HList a)
+ Language.Hakaru.Syntax.Datum: dCons_ :: Sing a -> ast a -> ast (HList a) -> Datum ast (HList a)
+ Language.Hakaru.Syntax.Datum: dFalse :: Datum ast HBool
+ Language.Hakaru.Syntax.Datum: dJust :: (SingI a) => ast a -> Datum ast (HMaybe a)
+ Language.Hakaru.Syntax.Datum: dJust_ :: Sing a -> ast a -> Datum ast (HMaybe a)
+ Language.Hakaru.Syntax.Datum: dLeft :: (SingI a, SingI b) => ast a -> Datum ast (HEither a b)
+ Language.Hakaru.Syntax.Datum: dLeft_ :: Sing a -> Sing b -> ast a -> Datum ast (HEither a b)
+ Language.Hakaru.Syntax.Datum: dNil :: (SingI a) => Datum ast (HList a)
+ Language.Hakaru.Syntax.Datum: dNil_ :: Sing a -> Datum ast (HList a)
+ Language.Hakaru.Syntax.Datum: dNothing :: (SingI a) => Datum ast (HMaybe a)
+ Language.Hakaru.Syntax.Datum: dNothing_ :: Sing a -> Datum ast (HMaybe a)
+ Language.Hakaru.Syntax.Datum: dPair :: (SingI a, SingI b) => ast a -> ast b -> Datum ast (HPair a b)
+ Language.Hakaru.Syntax.Datum: dPair_ :: Sing a -> Sing b -> ast a -> ast b -> Datum ast (HPair a b)
+ Language.Hakaru.Syntax.Datum: dRight :: (SingI a, SingI b) => ast b -> Datum ast (HEither a b)
+ Language.Hakaru.Syntax.Datum: dRight_ :: Sing a -> Sing b -> ast b -> Datum ast (HEither a b)
+ Language.Hakaru.Syntax.Datum: dTrue :: Datum ast HBool
+ Language.Hakaru.Syntax.Datum: dUnit :: Datum ast HUnit
+ Language.Hakaru.Syntax.Datum: data Branch (a :: Hakaru) (abt :: [Hakaru] -> Hakaru -> *) (b :: Hakaru)
+ Language.Hakaru.Syntax.Datum: data Datum :: (Hakaru -> *) -> Hakaru -> *
+ Language.Hakaru.Syntax.Datum: data DatumCode :: [[HakaruFun]] -> (Hakaru -> *) -> Hakaru -> *
+ Language.Hakaru.Syntax.Datum: data DatumFun :: HakaruFun -> (Hakaru -> *) -> Hakaru -> *
+ Language.Hakaru.Syntax.Datum: data DatumStruct :: [HakaruFun] -> (Hakaru -> *) -> Hakaru -> *
+ Language.Hakaru.Syntax.Datum: data GBranch (a :: Hakaru) (r :: *)
+ Language.Hakaru.Syntax.Datum: data PDatumCode :: [[HakaruFun]] -> [Hakaru] -> Hakaru -> *
+ Language.Hakaru.Syntax.Datum: data PDatumFun :: HakaruFun -> [Hakaru] -> Hakaru -> *
+ Language.Hakaru.Syntax.Datum: data PDatumStruct :: [HakaruFun] -> [Hakaru] -> Hakaru -> *
+ Language.Hakaru.Syntax.Datum: data Pattern :: [Hakaru] -> Hakaru -> *
+ Language.Hakaru.Syntax.Datum: datumHint :: Datum ast (HData' t) -> Text
+ Language.Hakaru.Syntax.Datum: datumType :: Datum ast (HData' t) -> Sing (HData' t)
+ Language.Hakaru.Syntax.Datum: instance Data.Foldable.Foldable (Language.Hakaru.Syntax.Datum.GBranch a)
+ Language.Hakaru.Syntax.Datum: instance Data.Traversable.Traversable (Language.Hakaru.Syntax.Datum.GBranch a)
+ Language.Hakaru.Syntax.Datum: instance GHC.Base.Functor (Language.Hakaru.Syntax.Datum.GBranch a)
+ Language.Hakaru.Syntax.Datum: instance GHC.Classes.Eq (Language.Hakaru.Syntax.Datum.PDatumCode xss vars a)
+ Language.Hakaru.Syntax.Datum: instance GHC.Classes.Eq (Language.Hakaru.Syntax.Datum.PDatumFun x vars a)
+ Language.Hakaru.Syntax.Datum: instance GHC.Classes.Eq (Language.Hakaru.Syntax.Datum.PDatumStruct xs vars a)
+ Language.Hakaru.Syntax.Datum: instance GHC.Classes.Eq (Language.Hakaru.Syntax.Datum.Pattern vars a)
+ Language.Hakaru.Syntax.Datum: instance GHC.Show.Show (Language.Hakaru.Syntax.Datum.PDatumCode xss vars a)
+ Language.Hakaru.Syntax.Datum: instance GHC.Show.Show (Language.Hakaru.Syntax.Datum.PDatumFun x vars a)
+ Language.Hakaru.Syntax.Datum: instance GHC.Show.Show (Language.Hakaru.Syntax.Datum.PDatumStruct xs vars a)
+ Language.Hakaru.Syntax.Datum: instance GHC.Show.Show (Language.Hakaru.Syntax.Datum.Pattern vars a)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Eq1 (Language.Hakaru.Syntax.Datum.PDatumCode xss vars)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Eq1 (Language.Hakaru.Syntax.Datum.PDatumFun x vars)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Eq1 (Language.Hakaru.Syntax.Datum.PDatumStruct xs vars)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Eq1 (Language.Hakaru.Syntax.Datum.Pattern vars)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Eq1 ast => GHC.Classes.Eq (Language.Hakaru.Syntax.Datum.Datum ast a)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Eq1 ast => GHC.Classes.Eq (Language.Hakaru.Syntax.Datum.DatumCode xss ast a)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Eq1 ast => GHC.Classes.Eq (Language.Hakaru.Syntax.Datum.DatumFun x ast a)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Eq1 ast => GHC.Classes.Eq (Language.Hakaru.Syntax.Datum.DatumStruct xs ast a)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Eq1 ast => Language.Hakaru.Syntax.IClasses.Eq1 (Language.Hakaru.Syntax.Datum.Datum ast)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Eq1 ast => Language.Hakaru.Syntax.IClasses.Eq1 (Language.Hakaru.Syntax.Datum.DatumCode xss ast)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Eq1 ast => Language.Hakaru.Syntax.IClasses.Eq1 (Language.Hakaru.Syntax.Datum.DatumFun x ast)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Eq1 ast => Language.Hakaru.Syntax.IClasses.Eq1 (Language.Hakaru.Syntax.Datum.DatumStruct xs ast)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Eq1 ast => Language.Hakaru.Syntax.IClasses.JmEq1 (Language.Hakaru.Syntax.Datum.Datum ast)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Eq2 (Language.Hakaru.Syntax.Datum.PDatumCode xss)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Eq2 (Language.Hakaru.Syntax.Datum.PDatumFun x)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Eq2 (Language.Hakaru.Syntax.Datum.PDatumStruct xs)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Eq2 Language.Hakaru.Syntax.Datum.Pattern
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Eq2 abt => GHC.Classes.Eq (Language.Hakaru.Syntax.Datum.Branch a abt b)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Eq2 abt => Language.Hakaru.Syntax.IClasses.Eq1 (Language.Hakaru.Syntax.Datum.Branch a abt)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Foldable11 (Language.Hakaru.Syntax.Datum.DatumCode xss)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Foldable11 (Language.Hakaru.Syntax.Datum.DatumFun x)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Foldable11 (Language.Hakaru.Syntax.Datum.DatumStruct xs)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Foldable11 Language.Hakaru.Syntax.Datum.Datum
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Foldable21 (Language.Hakaru.Syntax.Datum.Branch a)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Functor11 (Language.Hakaru.Syntax.Datum.DatumCode xss)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Functor11 (Language.Hakaru.Syntax.Datum.DatumFun x)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Functor11 (Language.Hakaru.Syntax.Datum.DatumStruct xs)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Functor11 Language.Hakaru.Syntax.Datum.Datum
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Functor21 (Language.Hakaru.Syntax.Datum.Branch a)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Show1 (Language.Hakaru.Syntax.Datum.PDatumCode xss vars)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Show1 (Language.Hakaru.Syntax.Datum.PDatumFun x vars)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Show1 (Language.Hakaru.Syntax.Datum.PDatumStruct xs vars)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Show1 (Language.Hakaru.Syntax.Datum.Pattern vars)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Show1 ast => GHC.Show.Show (Language.Hakaru.Syntax.Datum.Datum ast a)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Show1 ast => GHC.Show.Show (Language.Hakaru.Syntax.Datum.DatumCode xss ast a)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Show1 ast => GHC.Show.Show (Language.Hakaru.Syntax.Datum.DatumFun x ast a)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Show1 ast => GHC.Show.Show (Language.Hakaru.Syntax.Datum.DatumStruct xs ast a)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Show1 ast => Language.Hakaru.Syntax.IClasses.Show1 (Language.Hakaru.Syntax.Datum.Datum ast)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Show1 ast => Language.Hakaru.Syntax.IClasses.Show1 (Language.Hakaru.Syntax.Datum.DatumCode xss ast)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Show1 ast => Language.Hakaru.Syntax.IClasses.Show1 (Language.Hakaru.Syntax.Datum.DatumFun x ast)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Show1 ast => Language.Hakaru.Syntax.IClasses.Show1 (Language.Hakaru.Syntax.Datum.DatumStruct xs ast)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Show2 (Language.Hakaru.Syntax.Datum.PDatumCode xss)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Show2 (Language.Hakaru.Syntax.Datum.PDatumFun x)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Show2 (Language.Hakaru.Syntax.Datum.PDatumStruct xs)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Show2 Language.Hakaru.Syntax.Datum.Pattern
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Show2 abt => GHC.Show.Show (Language.Hakaru.Syntax.Datum.Branch a abt b)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Show2 abt => Language.Hakaru.Syntax.IClasses.Show1 (Language.Hakaru.Syntax.Datum.Branch a abt)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Traversable11 (Language.Hakaru.Syntax.Datum.DatumCode xss)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Traversable11 (Language.Hakaru.Syntax.Datum.DatumFun x)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Traversable11 (Language.Hakaru.Syntax.Datum.DatumStruct xs)
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Traversable11 Language.Hakaru.Syntax.Datum.Datum
+ Language.Hakaru.Syntax.Datum: instance Language.Hakaru.Syntax.IClasses.Traversable21 (Language.Hakaru.Syntax.Datum.Branch a)
+ Language.Hakaru.Syntax.Datum: pCons :: Pattern vars1 a -> Pattern vars2 (HList a) -> Pattern (vars1 ++ vars2) (HList a)
+ Language.Hakaru.Syntax.Datum: pFalse :: Pattern '[] HBool
+ Language.Hakaru.Syntax.Datum: pJust :: Pattern vars a -> Pattern vars (HMaybe a)
+ Language.Hakaru.Syntax.Datum: pLeft :: Pattern vars a -> Pattern vars (HEither a b)
+ Language.Hakaru.Syntax.Datum: pNil :: Pattern '[] (HList a)
+ Language.Hakaru.Syntax.Datum: pNothing :: Pattern '[] (HMaybe a)
+ Language.Hakaru.Syntax.Datum: pPair :: Pattern vars1 a -> Pattern vars2 b -> Pattern (vars1 ++ vars2) (HPair a b)
+ Language.Hakaru.Syntax.Datum: pRight :: Pattern vars b -> Pattern vars (HEither a b)
+ Language.Hakaru.Syntax.Datum: pTrue :: Pattern '[] HBool
+ Language.Hakaru.Syntax.Datum: pUnit :: Pattern '[] HUnit
+ Language.Hakaru.Syntax.DatumABT: fromGBranch :: (ABT syn abt) => GBranch a (abt '[] b) -> Branch a abt b
+ Language.Hakaru.Syntax.DatumABT: toGBranch :: (ABT syn abt) => Branch a abt b -> GBranch a (abt '[] b)
+ Language.Hakaru.Syntax.DatumCase: GotStuck :: MatchResult
+ Language.Hakaru.Syntax.DatumCase: GotStuck_ :: MatchState
+ Language.Hakaru.Syntax.DatumCase: Matched :: !(Assocs ast) -> !(abt '[] a) -> MatchResult
+ Language.Hakaru.Syntax.DatumCase: Matched_ :: (DList (Assoc ast)) -> (List1 Variable vars) -> MatchState
+ Language.Hakaru.Syntax.DatumCase: data MatchResult (ast :: Hakaru -> *) (abt :: [Hakaru] -> Hakaru -> *) (a :: Hakaru)
+ Language.Hakaru.Syntax.DatumCase: data MatchState (ast :: Hakaru -> *) (vars :: [Hakaru])
+ Language.Hakaru.Syntax.DatumCase: instance (Language.Hakaru.Syntax.IClasses.Show1 ast, Language.Hakaru.Syntax.IClasses.Show2 abt) => GHC.Show.Show (Language.Hakaru.Syntax.DatumCase.MatchResult ast abt a)
+ Language.Hakaru.Syntax.DatumCase: instance (Language.Hakaru.Syntax.IClasses.Show1 ast, Language.Hakaru.Syntax.IClasses.Show2 abt) => Language.Hakaru.Syntax.IClasses.Show1 (Language.Hakaru.Syntax.DatumCase.MatchResult ast abt)
+ Language.Hakaru.Syntax.DatumCase: instance Language.Hakaru.Syntax.IClasses.Show1 ast => GHC.Show.Show (Language.Hakaru.Syntax.DatumCase.MatchState ast vars)
+ Language.Hakaru.Syntax.DatumCase: matchBranch :: (ABT Term abt, Monad m) => DatumEvaluator ast m -> ast a -> Branch a abt b -> m (Maybe (MatchResult ast abt b))
+ Language.Hakaru.Syntax.DatumCase: matchBranches :: (ABT Term abt, Monad m) => DatumEvaluator ast m -> ast a -> [Branch a abt b] -> m (Maybe (MatchResult ast abt b))
+ Language.Hakaru.Syntax.DatumCase: matchPattern :: (Monad m) => DatumEvaluator ast m -> ast a -> Pattern vars1 a -> List1 Variable (vars1 ++ vars2) -> m (Maybe (MatchState ast vars2))
+ Language.Hakaru.Syntax.DatumCase: matchTopPattern :: (Monad m) => DatumEvaluator ast m -> ast a -> Pattern vars a -> List1 Variable vars -> m (Maybe (MatchState ast '[]))
+ Language.Hakaru.Syntax.DatumCase: type DatumEvaluator ast m = forall t. ast (HData' t) -> m (Maybe (Datum ast (HData' t)))
+ Language.Hakaru.Syntax.DatumCase: viewDatum :: (ABT Term abt) => abt '[] (HData' t) -> Maybe (Datum (abt '[]) (HData' t))
+ Language.Hakaru.Syntax.IClasses: DList1 :: (forall ys. List1 a ys -> List1 a (xs ++ ys)) -> DList1 a xs
+ Language.Hakaru.Syntax.IClasses: Fix11 :: f (Fix11 f) i -> Fix11
+ Language.Hakaru.Syntax.IClasses: Lift1 :: a -> Lift1
+ Language.Hakaru.Syntax.IClasses: Lift2 :: a -> Lift2
+ Language.Hakaru.Syntax.IClasses: Pair1 :: (a i) -> (b i) -> Pair1
+ Language.Hakaru.Syntax.IClasses: Pair2 :: (a i j) -> (b i j) -> Pair2
+ Language.Hakaru.Syntax.IClasses: Some1 :: !(a i) -> Some1
+ Language.Hakaru.Syntax.IClasses: Some2 :: !(a i j) -> Some2
+ Language.Hakaru.Syntax.IClasses: [Cons1] :: a x -> List1 a xs -> List1 a (x : xs)
+ Language.Hakaru.Syntax.IClasses: [Nil1] :: List1 a '[]
+ Language.Hakaru.Syntax.IClasses: [Refl] :: TypeEq a a
+ Language.Hakaru.Syntax.IClasses: [unDList1] :: DList1 a xs -> forall ys. List1 a ys -> List1 a (xs ++ ys)
+ Language.Hakaru.Syntax.IClasses: [unFix11] :: Fix11 -> f (Fix11 f) i
+ Language.Hakaru.Syntax.IClasses: [unLift1] :: Lift1 -> a
+ Language.Hakaru.Syntax.IClasses: [unLift2] :: Lift2 -> a
+ Language.Hakaru.Syntax.IClasses: ana11 :: forall f a j. (Functor11 f) => (forall i. a i -> f a i) -> a j -> Fix11 f j
+ Language.Hakaru.Syntax.IClasses: append1 :: List1 a xs -> List1 a ys -> List1 a (xs ++ ys)
+ Language.Hakaru.Syntax.IClasses: cata11 :: forall f a j. (Functor11 f) => (forall i. f a i -> a i) -> Fix11 f j -> a j
+ Language.Hakaru.Syntax.IClasses: class Eq1 (a :: k -> *)
+ Language.Hakaru.Syntax.IClasses: class Eq2 (a :: k1 -> k2 -> *)
+ Language.Hakaru.Syntax.IClasses: class Functor11 f => Foldable11 (f :: (k1 -> *) -> k2 -> *) where fold11 = foldMap11 unLift1 foldMap11 f = fold11 . fmap11 (Lift1 . f)
+ Language.Hakaru.Syntax.IClasses: class Functor21 f => Foldable21 (f :: (k1 -> k2 -> *) -> k3 -> *) where fold21 = foldMap21 unLift2 foldMap21 f = fold21 . fmap21 (Lift2 . f)
+ Language.Hakaru.Syntax.IClasses: class Functor22 f => Foldable22 (f :: (k1 -> k2 -> *) -> k3 -> k4 -> *) where fold22 = foldMap22 unLift2 foldMap22 f = fold22 . fmap22 (Lift2 . f)
+ Language.Hakaru.Syntax.IClasses: class Functor11 (f :: (k1 -> *) -> k2 -> *)
+ Language.Hakaru.Syntax.IClasses: class Functor12 (f :: (k1 -> *) -> k2 -> k3 -> *)
+ Language.Hakaru.Syntax.IClasses: class Functor21 (f :: (k1 -> k2 -> *) -> k3 -> *)
+ Language.Hakaru.Syntax.IClasses: class Functor22 (f :: (k1 -> k2 -> *) -> k3 -> k4 -> *)
+ Language.Hakaru.Syntax.IClasses: class Eq1 a => JmEq1 (a :: k -> *)
+ Language.Hakaru.Syntax.IClasses: class Eq2 a => JmEq2 (a :: k1 -> k2 -> *)
+ Language.Hakaru.Syntax.IClasses: class Show1 (a :: k -> *) where showsPrec1 _ x s = show1 x ++ s show1 x = shows1 x ""
+ Language.Hakaru.Syntax.IClasses: class Show2 (a :: k1 -> k2 -> *) where showsPrec2 _ x s = show2 x ++ s show2 x = shows2 x ""
+ Language.Hakaru.Syntax.IClasses: class Foldable11 t => Traversable11 (t :: (k1 -> *) -> k2 -> *)
+ Language.Hakaru.Syntax.IClasses: class Foldable21 t => Traversable21 (t :: (k1 -> k2 -> *) -> k3 -> *)
+ Language.Hakaru.Syntax.IClasses: class Foldable22 t => Traversable22 (t :: (k1 -> k2 -> *) -> k3 -> k4 -> *)
+ Language.Hakaru.Syntax.IClasses: congruence :: TypeEq a b -> TypeEq (f a) (f b)
+ Language.Hakaru.Syntax.IClasses: dappend1 :: DList1 a xs -> DList1 a ys -> DList1 a (xs ++ ys)
+ Language.Hakaru.Syntax.IClasses: data List1 :: (k -> *) -> [k] -> *
+ Language.Hakaru.Syntax.IClasses: data Pair1 (a :: k -> *) (b :: k -> *) (i :: k)
+ Language.Hakaru.Syntax.IClasses: data Pair2 (a :: k1 -> k2 -> *) (b :: k1 -> k2 -> *) (i :: k1) (j :: k2)
+ Language.Hakaru.Syntax.IClasses: data Some1 (a :: k -> *)
+ Language.Hakaru.Syntax.IClasses: data Some2 (a :: k1 -> k2 -> *)
+ Language.Hakaru.Syntax.IClasses: data TypeEq :: k -> k -> *
+ Language.Hakaru.Syntax.IClasses: dcons1 :: a x -> DList1 a xs -> DList1 a (x : xs)
+ Language.Hakaru.Syntax.IClasses: dnil1 :: DList1 a '[]
+ Language.Hakaru.Syntax.IClasses: dsingleton1 :: a x -> DList1 a '[x]
+ Language.Hakaru.Syntax.IClasses: dsnoc1 :: DList1 a xs -> a x -> DList1 a (xs ++ '[x])
+ Language.Hakaru.Syntax.IClasses: eq1 :: Eq1 a => a i -> a i -> Bool
+ Language.Hakaru.Syntax.IClasses: eq2 :: Eq2 a => a i j -> a i j -> Bool
+ Language.Hakaru.Syntax.IClasses: eqAppendAssoc :: proxy1 xs -> proxy2 ys -> proxy3 zs -> TypeEq ((xs ++ ys) ++ zs) (xs ++ (ys ++ zs))
+ Language.Hakaru.Syntax.IClasses: eqAppendIdentity :: proxy xs -> TypeEq xs (xs ++ '[])
+ Language.Hakaru.Syntax.IClasses: fmap11 :: Functor11 f => (forall i. a i -> b i) -> f a j -> f b j
+ Language.Hakaru.Syntax.IClasses: fmap12 :: Functor12 f => (forall i. a i -> b i) -> f a j l -> f b j l
+ Language.Hakaru.Syntax.IClasses: fmap21 :: Functor21 f => (forall h i. a h i -> b h i) -> f a j -> f b j
+ Language.Hakaru.Syntax.IClasses: fmap22 :: Functor22 f => (forall h i. a h i -> b h i) -> f a j l -> f b j l
+ Language.Hakaru.Syntax.IClasses: fold11 :: (Foldable11 f, Monoid m) => f (Lift1 m) i -> m
+ Language.Hakaru.Syntax.IClasses: fold21 :: (Foldable21 f, Monoid m) => f (Lift2 m) j -> m
+ Language.Hakaru.Syntax.IClasses: fold22 :: (Foldable22 f, Monoid m) => f (Lift2 m) j l -> m
+ Language.Hakaru.Syntax.IClasses: foldMap11 :: (Foldable11 f, Monoid m) => (forall i. a i -> m) -> f a j -> m
+ Language.Hakaru.Syntax.IClasses: foldMap21 :: (Foldable21 f, Monoid m) => (forall h i. a h i -> m) -> f a j -> m
+ Language.Hakaru.Syntax.IClasses: foldMap22 :: (Foldable22 f, Monoid m) => (forall h i. a h i -> m) -> f a j l -> m
+ Language.Hakaru.Syntax.IClasses: fromList1 :: List1 a xs -> DList1 a xs
+ Language.Hakaru.Syntax.IClasses: fst1 :: Pair1 a b i -> a i
+ Language.Hakaru.Syntax.IClasses: fst2 :: Pair2 a b i j -> a i j
+ Language.Hakaru.Syntax.IClasses: hylo11 :: forall f a b j. (Functor11 f) => (forall i. a i -> f a i) -> (forall i. f b i -> b i) -> a j -> b j
+ Language.Hakaru.Syntax.IClasses: instance Control.Category.Category Language.Hakaru.Syntax.IClasses.TypeEq
+ Language.Hakaru.Syntax.IClasses: instance GHC.Classes.Eq a => Language.Hakaru.Syntax.IClasses.Eq1 (Language.Hakaru.Syntax.IClasses.Lift1 a)
+ Language.Hakaru.Syntax.IClasses: instance GHC.Classes.Eq a => Language.Hakaru.Syntax.IClasses.Eq2 (Language.Hakaru.Syntax.IClasses.Lift2 a)
+ Language.Hakaru.Syntax.IClasses: instance GHC.Show.Show a => Language.Hakaru.Syntax.IClasses.Show1 (Language.Hakaru.Syntax.IClasses.Lift1 a)
+ Language.Hakaru.Syntax.IClasses: instance GHC.Show.Show a => Language.Hakaru.Syntax.IClasses.Show2 (Language.Hakaru.Syntax.IClasses.Lift2 a)
+ Language.Hakaru.Syntax.IClasses: instance Language.Hakaru.Syntax.IClasses.Foldable11 Language.Hakaru.Syntax.IClasses.List1
+ Language.Hakaru.Syntax.IClasses: instance Language.Hakaru.Syntax.IClasses.Functor11 Language.Hakaru.Syntax.IClasses.List1
+ Language.Hakaru.Syntax.IClasses: instance Language.Hakaru.Syntax.IClasses.Traversable11 Language.Hakaru.Syntax.IClasses.List1
+ Language.Hakaru.Syntax.IClasses: instance forall a k (i :: k). GHC.Classes.Eq a => GHC.Classes.Eq (Language.Hakaru.Syntax.IClasses.Lift1 a i)
+ Language.Hakaru.Syntax.IClasses: instance forall a k (i :: k). GHC.Classes.Ord a => GHC.Classes.Ord (Language.Hakaru.Syntax.IClasses.Lift1 a i)
+ Language.Hakaru.Syntax.IClasses: instance forall a k (i :: k). GHC.Read.Read a => GHC.Read.Read (Language.Hakaru.Syntax.IClasses.Lift1 a i)
+ Language.Hakaru.Syntax.IClasses: instance forall a k (i :: k). GHC.Show.Show a => GHC.Show.Show (Language.Hakaru.Syntax.IClasses.Lift1 a i)
+ Language.Hakaru.Syntax.IClasses: instance forall a k1 (i :: k1) k2 (j :: k2). GHC.Classes.Eq a => GHC.Classes.Eq (Language.Hakaru.Syntax.IClasses.Lift2 a i j)
+ Language.Hakaru.Syntax.IClasses: instance forall a k1 (i :: k1) k2 (j :: k2). GHC.Classes.Ord a => GHC.Classes.Ord (Language.Hakaru.Syntax.IClasses.Lift2 a i j)
+ Language.Hakaru.Syntax.IClasses: instance forall a k1 (i :: k1) k2 (j :: k2). GHC.Read.Read a => GHC.Read.Read (Language.Hakaru.Syntax.IClasses.Lift2 a i j)
+ Language.Hakaru.Syntax.IClasses: instance forall a k1 (i :: k1) k2 (j :: k2). GHC.Show.Show a => GHC.Show.Show (Language.Hakaru.Syntax.IClasses.Lift2 a i j)
+ Language.Hakaru.Syntax.IClasses: instance forall k (a :: k -> GHC.Types.*) (b :: k -> GHC.Types.*) (i :: k). (Language.Hakaru.Syntax.IClasses.Show1 a, Language.Hakaru.Syntax.IClasses.Show1 b) => GHC.Show.Show (Language.Hakaru.Syntax.IClasses.Pair1 a b i)
+ Language.Hakaru.Syntax.IClasses: instance forall k (a :: k -> GHC.Types.*) (b :: k -> GHC.Types.*). (Language.Hakaru.Syntax.IClasses.Show1 a, Language.Hakaru.Syntax.IClasses.Show1 b) => Language.Hakaru.Syntax.IClasses.Show1 (Language.Hakaru.Syntax.IClasses.Pair1 a b)
+ Language.Hakaru.Syntax.IClasses: instance forall k (a :: k -> GHC.Types.*) (xs :: [k]). Language.Hakaru.Syntax.IClasses.Eq1 a => GHC.Classes.Eq (Language.Hakaru.Syntax.IClasses.List1 a xs)
+ Language.Hakaru.Syntax.IClasses: instance forall k (a :: k -> GHC.Types.*) (xs :: [k]). Language.Hakaru.Syntax.IClasses.Show1 a => GHC.Show.Show (Language.Hakaru.Syntax.IClasses.List1 a xs)
+ Language.Hakaru.Syntax.IClasses: instance forall k (a :: k -> GHC.Types.*). Language.Hakaru.Syntax.IClasses.Eq1 a => Language.Hakaru.Syntax.IClasses.Eq1 (Language.Hakaru.Syntax.IClasses.List1 a)
+ Language.Hakaru.Syntax.IClasses: instance forall k (a :: k -> GHC.Types.*). Language.Hakaru.Syntax.IClasses.JmEq1 a => GHC.Classes.Eq (Language.Hakaru.Syntax.IClasses.Some1 a)
+ Language.Hakaru.Syntax.IClasses: instance forall k (a :: k -> GHC.Types.*). Language.Hakaru.Syntax.IClasses.JmEq1 a => Language.Hakaru.Syntax.IClasses.JmEq1 (Language.Hakaru.Syntax.IClasses.List1 a)
+ Language.Hakaru.Syntax.IClasses: instance forall k (a :: k -> GHC.Types.*). Language.Hakaru.Syntax.IClasses.Show1 a => GHC.Show.Show (Language.Hakaru.Syntax.IClasses.Some1 a)
+ Language.Hakaru.Syntax.IClasses: instance forall k (a :: k -> GHC.Types.*). Language.Hakaru.Syntax.IClasses.Show1 a => Language.Hakaru.Syntax.IClasses.Show1 (Language.Hakaru.Syntax.IClasses.List1 a)
+ Language.Hakaru.Syntax.IClasses: instance forall k k1 (a :: k1 -> k -> GHC.Types.*) (b :: k1 -> k -> GHC.Types.*) (i :: k1). (Language.Hakaru.Syntax.IClasses.Show2 a, Language.Hakaru.Syntax.IClasses.Show2 b) => Language.Hakaru.Syntax.IClasses.Show1 (Language.Hakaru.Syntax.IClasses.Pair2 a b i)
+ Language.Hakaru.Syntax.IClasses: instance forall k k1 a (i :: k1). GHC.Classes.Eq a => Language.Hakaru.Syntax.IClasses.Eq1 (Language.Hakaru.Syntax.IClasses.Lift2 a i)
+ Language.Hakaru.Syntax.IClasses: instance forall k k1 a (i :: k1). GHC.Show.Show a => Language.Hakaru.Syntax.IClasses.Show1 (Language.Hakaru.Syntax.IClasses.Lift2 a i)
+ Language.Hakaru.Syntax.IClasses: instance forall k2 k1 (a :: k1 -> k2 -> GHC.Types.*) (b :: k1 -> k2 -> GHC.Types.*) (i :: k1) (j :: k2). (Language.Hakaru.Syntax.IClasses.Show2 a, Language.Hakaru.Syntax.IClasses.Show2 b) => GHC.Show.Show (Language.Hakaru.Syntax.IClasses.Pair2 a b i j)
+ Language.Hakaru.Syntax.IClasses: instance forall k2 k1 (a :: k1 -> k2 -> GHC.Types.*) (b :: k1 -> k2 -> GHC.Types.*). (Language.Hakaru.Syntax.IClasses.Show2 a, Language.Hakaru.Syntax.IClasses.Show2 b) => Language.Hakaru.Syntax.IClasses.Show2 (Language.Hakaru.Syntax.IClasses.Pair2 a b)
+ Language.Hakaru.Syntax.IClasses: instance forall k2 k1 (a :: k1 -> k2 -> GHC.Types.*). Language.Hakaru.Syntax.IClasses.JmEq2 a => GHC.Classes.Eq (Language.Hakaru.Syntax.IClasses.Some2 a)
+ Language.Hakaru.Syntax.IClasses: instance forall k2 k1 (a :: k1 -> k2 -> GHC.Types.*). Language.Hakaru.Syntax.IClasses.Show2 a => GHC.Show.Show (Language.Hakaru.Syntax.IClasses.Some2 a)
+ Language.Hakaru.Syntax.IClasses: jmEq1 :: JmEq1 a => a i -> a j -> Maybe (TypeEq i j)
+ Language.Hakaru.Syntax.IClasses: jmEq2 :: JmEq2 a => a i1 j1 -> a i2 j2 -> Maybe (TypeEq i1 i2, TypeEq j1 j2)
+ Language.Hakaru.Syntax.IClasses: newtype DList1 a xs
+ Language.Hakaru.Syntax.IClasses: newtype Fix11 (f :: (k -> *) -> k -> *) (i :: k)
+ Language.Hakaru.Syntax.IClasses: newtype Lift1 (a :: *) (i :: k)
+ Language.Hakaru.Syntax.IClasses: newtype Lift2 (a :: *) (i :: k1) (j :: k2)
+ Language.Hakaru.Syntax.IClasses: show1 :: Show1 a => a i -> String
+ Language.Hakaru.Syntax.IClasses: show2 :: Show2 a => a i j -> String
+ Language.Hakaru.Syntax.IClasses: showList1 :: (Show1 a) => [a i] -> ShowS
+ Language.Hakaru.Syntax.IClasses: showList2 :: Show2 a => [a i j] -> ShowS
+ Language.Hakaru.Syntax.IClasses: showListWith :: (a -> ShowS) -> [a] -> ShowS
+ Language.Hakaru.Syntax.IClasses: showParen_0 :: Show a => Int -> String -> a -> ShowS
+ Language.Hakaru.Syntax.IClasses: showParen_01 :: (Show b, Show1 a) => Int -> String -> b -> a i -> ShowS
+ Language.Hakaru.Syntax.IClasses: showParen_010 :: (Show a, Show1 b, Show c) => Int -> String -> a -> b i -> c -> ShowS
+ Language.Hakaru.Syntax.IClasses: showParen_011 :: (Show a, Show1 b, Show1 c) => Int -> String -> a -> b i -> c j -> ShowS
+ Language.Hakaru.Syntax.IClasses: showParen_02 :: (Show b, Show2 a) => Int -> String -> b -> a i j -> ShowS
+ Language.Hakaru.Syntax.IClasses: showParen_1 :: Show1 a => Int -> String -> a i -> ShowS
+ Language.Hakaru.Syntax.IClasses: showParen_11 :: (Show1 a, Show1 b) => Int -> String -> a i -> b j -> ShowS
+ Language.Hakaru.Syntax.IClasses: showParen_111 :: (Show1 a, Show1 b, Show1 c) => Int -> String -> a i -> b j -> c k -> ShowS
+ Language.Hakaru.Syntax.IClasses: showParen_12 :: (Show1 a, Show2 b) => Int -> String -> a i -> b j l -> ShowS
+ Language.Hakaru.Syntax.IClasses: showParen_2 :: Show2 a => Int -> String -> a i j -> ShowS
+ Language.Hakaru.Syntax.IClasses: showParen_22 :: (Show2 a, Show2 b) => Int -> String -> a i1 j1 -> b i2 j2 -> ShowS
+ Language.Hakaru.Syntax.IClasses: showTuple :: [ShowS] -> ShowS
+ Language.Hakaru.Syntax.IClasses: shows1 :: (Show1 a) => a i -> ShowS
+ Language.Hakaru.Syntax.IClasses: shows2 :: (Show2 a) => a i j -> ShowS
+ Language.Hakaru.Syntax.IClasses: showsPrec1 :: Show1 a => Int -> a i -> ShowS
+ Language.Hakaru.Syntax.IClasses: showsPrec2 :: Show2 a => Int -> a i j -> ShowS
+ Language.Hakaru.Syntax.IClasses: snd1 :: Pair1 a b i -> b i
+ Language.Hakaru.Syntax.IClasses: snd2 :: Pair2 a b i j -> b i j
+ Language.Hakaru.Syntax.IClasses: symmetry :: TypeEq a b -> TypeEq b a
+ Language.Hakaru.Syntax.IClasses: toList1 :: DList1 a xs -> List1 a xs
+ Language.Hakaru.Syntax.IClasses: transitivity :: TypeEq a b -> TypeEq b c -> TypeEq a c
+ Language.Hakaru.Syntax.IClasses: traverse11 :: (Traversable11 t, Applicative f) => (forall i. a i -> f (b i)) -> t a j -> f (t b j)
+ Language.Hakaru.Syntax.IClasses: traverse21 :: (Traversable21 t, Applicative f) => (forall h i. a h i -> f (b h i)) -> t a j -> f (t b j)
+ Language.Hakaru.Syntax.IClasses: traverse22 :: (Traversable22 t, Applicative f) => (forall h i. a h i -> f (b h i)) -> t a j l -> f (t b j l)
+ Language.Hakaru.Syntax.Prelude: (!) :: (ABT Term abt) => abt '[] (HArray a) -> abt '[] HNat -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: (&&) :: (ABT Term abt) => abt '[] HBool -> abt '[] HBool -> abt '[] HBool
+ Language.Hakaru.Syntax.Prelude: (*) :: (ABT Term abt, HSemiring_ a) => abt '[] a -> abt '[] a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: (**) :: (RealProb a, ABT Term abt) => abt '[] HProb -> abt '[] a -> abt '[] HProb
+ Language.Hakaru.Syntax.Prelude: (*>) :: (ABT Term abt, SingI a) => abt '[] (HMeasure a) -> abt '[] (HMeasure b) -> abt '[] (HMeasure b)
+ Language.Hakaru.Syntax.Prelude: (+) :: (ABT Term abt, HSemiring_ a) => abt '[] a -> abt '[] a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: (-) :: (ABT Term abt, HRing_ a) => abt '[] a -> abt '[] a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: (/) :: (ABT Term abt, HFractional_ a) => abt '[] a -> abt '[] a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: (/=) :: (ABT Term abt, HEq_ a) => abt '[] a -> abt '[] a -> abt '[] HBool
+ Language.Hakaru.Syntax.Prelude: (<$>) :: (ABT Term abt, SingI a) => (abt '[] a -> abt '[] b) -> abt '[] (HMeasure a) -> abt '[] (HMeasure b)
+ Language.Hakaru.Syntax.Prelude: (<) :: (ABT Term abt, HOrd_ a) => abt '[] a -> abt '[] a -> abt '[] HBool
+ Language.Hakaru.Syntax.Prelude: (<*) :: (ABT Term abt, SingI a, SingI b) => abt '[] (HMeasure a) -> abt '[] (HMeasure b) -> abt '[] (HMeasure a)
+ Language.Hakaru.Syntax.Prelude: (<*>) :: (ABT Term abt, SingI a, SingI b) => abt '[] (HMeasure (a :-> b)) -> abt '[] (HMeasure a) -> abt '[] (HMeasure b)
+ Language.Hakaru.Syntax.Prelude: (<=) :: (ABT Term abt, HOrd_ a) => abt '[] a -> abt '[] a -> abt '[] HBool
+ Language.Hakaru.Syntax.Prelude: (<|>) :: (ABT Term abt) => abt '[] (HMeasure a) -> abt '[] (HMeasure a) -> abt '[] (HMeasure a)
+ Language.Hakaru.Syntax.Prelude: (==) :: (ABT Term abt, HEq_ a) => abt '[] a -> abt '[] a -> abt '[] HBool
+ Language.Hakaru.Syntax.Prelude: (>) :: (ABT Term abt, HOrd_ a) => abt '[] a -> abt '[] a -> abt '[] HBool
+ Language.Hakaru.Syntax.Prelude: (>=) :: (ABT Term abt, HOrd_ a) => abt '[] a -> abt '[] a -> abt '[] HBool
+ Language.Hakaru.Syntax.Prelude: (>>) :: (ABT Term abt, SingI a) => abt '[] (HMeasure a) -> abt '[] (HMeasure b) -> abt '[] (HMeasure b)
+ Language.Hakaru.Syntax.Prelude: (>>=) :: (ABT Term abt) => abt '[] (HMeasure a) -> (abt '[] a -> abt '[] (HMeasure b)) -> abt '[] (HMeasure b)
+ Language.Hakaru.Syntax.Prelude: (^) :: (ABT Term abt, HSemiring_ a) => abt '[] a -> abt '[] HNat -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: (^^) :: (ABT Term abt, HFractional_ a) => abt '[] a -> abt '[] HInt -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: (||) :: (ABT Term abt) => abt '[] HBool -> abt '[] HBool -> abt '[] HBool
+ Language.Hakaru.Syntax.Prelude: abs :: (ABT Term abt, HRing_ a) => abt '[] a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: abs_ :: (ABT Term abt, HRing_ a) => abt '[] a -> abt '[] (NonNegative a)
+ Language.Hakaru.Syntax.Prelude: acos :: (ABT Term abt) => abt '[] HReal -> abt '[] HReal
+ Language.Hakaru.Syntax.Prelude: acosh :: (ABT Term abt) => abt '[] HReal -> abt '[] HReal
+ Language.Hakaru.Syntax.Prelude: and :: (ABT Term abt) => [abt '[] HBool] -> abt '[] HBool
+ Language.Hakaru.Syntax.Prelude: ann_ :: (ABT Term abt) => Sing a -> abt '[] a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: app :: (ABT Term abt) => abt '[] (a :-> b) -> abt '[] a -> abt '[] b
+ Language.Hakaru.Syntax.Prelude: app2 :: (ABT Term abt) => abt '[] (a :-> (b :-> c)) -> abt '[] a -> abt '[] b -> abt '[] c
+ Language.Hakaru.Syntax.Prelude: app3 :: (ABT Term abt) => abt '[] (a :-> (b :-> (c :-> d))) -> abt '[] a -> abt '[] b -> abt '[] c -> abt '[] d
+ Language.Hakaru.Syntax.Prelude: appendV :: (ABT Term abt) => abt '[] (HArray a) -> abt '[] (HArray a) -> abt '[] (HArray a)
+ Language.Hakaru.Syntax.Prelude: array :: (ABT Term abt) => abt '[] HNat -> (abt '[] HNat -> abt '[] a) -> abt '[] (HArray a)
+ Language.Hakaru.Syntax.Prelude: arrayOp0_ :: (ABT Term abt) => ArrayOp '[] a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: arrayOp1_ :: (ABT Term abt) => ArrayOp '[a] b -> abt '[] a -> abt '[] b
+ Language.Hakaru.Syntax.Prelude: arrayOp2_ :: (ABT Term abt) => ArrayOp '[a, b] c -> abt '[] a -> abt '[] b -> abt '[] c
+ Language.Hakaru.Syntax.Prelude: arrayOp3_ :: (ABT Term abt) => ArrayOp '[a, b, c] d -> abt '[] a -> abt '[] b -> abt '[] c -> abt '[] d
+ Language.Hakaru.Syntax.Prelude: arrayWithVar :: (ABT Term abt) => abt '[] HNat -> Variable HNat -> abt '[] a -> abt '[] (HArray a)
+ Language.Hakaru.Syntax.Prelude: asin :: (ABT Term abt) => abt '[] HReal -> abt '[] HReal
+ Language.Hakaru.Syntax.Prelude: asinh :: (ABT Term abt) => abt '[] HReal -> abt '[] HReal
+ Language.Hakaru.Syntax.Prelude: atan :: (ABT Term abt) => abt '[] HReal -> abt '[] HReal
+ Language.Hakaru.Syntax.Prelude: atanh :: (ABT Term abt) => abt '[] HReal -> abt '[] HReal
+ Language.Hakaru.Syntax.Prelude: bern :: (ABT Term abt) => abt '[] HProb -> abt '[] (HMeasure HBool)
+ Language.Hakaru.Syntax.Prelude: beta :: (ABT Term abt) => abt '[] HProb -> abt '[] HProb -> abt '[] (HMeasure HProb)
+ Language.Hakaru.Syntax.Prelude: beta' :: (ABT Term abt) => abt '[] HProb -> abt '[] HProb -> abt '[] (HMeasure HProb)
+ Language.Hakaru.Syntax.Prelude: beta'' :: (ABT Term abt) => abt '[] HProb -> abt '[] HProb -> abt '[] (HMeasure HProb)
+ Language.Hakaru.Syntax.Prelude: betaFunc :: (ABT Term abt) => abt '[] HProb -> abt '[] HProb -> abt '[] HProb
+ Language.Hakaru.Syntax.Prelude: bindx :: (ABT Term abt, SingI a, SingI b) => abt '[] (HMeasure a) -> (abt '[] a -> abt '[] (HMeasure b)) -> abt '[] (HMeasure (HPair a b))
+ Language.Hakaru.Syntax.Prelude: binomial :: (ABT Term abt) => abt '[] HNat -> abt '[] HProb -> abt '[] (HMeasure HInt)
+ Language.Hakaru.Syntax.Prelude: bool_ :: (ABT Term abt) => Bool -> abt '[] HBool
+ Language.Hakaru.Syntax.Prelude: branch :: (ABT Term abt) => Pattern xs a -> abt xs b -> Branch a abt b
+ Language.Hakaru.Syntax.Prelude: case_ :: (ABT Term abt) => abt '[] a -> [Branch a abt b] -> abt '[] b
+ Language.Hakaru.Syntax.Prelude: categorical :: (ABT Term abt) => abt '[] (HArray HProb) -> abt '[] (HMeasure HNat)
+ Language.Hakaru.Syntax.Prelude: categorical' :: (ABT Term abt) => abt '[] (HArray HProb) -> abt '[] (HMeasure HNat)
+ Language.Hakaru.Syntax.Prelude: cauchy :: (ABT Term abt) => abt '[] HReal -> abt '[] HProb -> abt '[] (HMeasure HReal)
+ Language.Hakaru.Syntax.Prelude: chain :: (ABT Term abt, SingI s) => abt '[] HNat -> abt '[] s -> (abt '[] s -> abt '[] (HMeasure (HPair a s))) -> abt '[] (HMeasure (HPair (HArray a) s))
+ Language.Hakaru.Syntax.Prelude: chain' :: (ABT Term abt, SingI s, SingI a) => abt '[] (HArray (s :-> HMeasure (HPair a s))) -> abt '[] s -> abt '[] (HMeasure (HPair (HArray a) s))
+ Language.Hakaru.Syntax.Prelude: chi2 :: (ABT Term abt) => abt '[] HProb -> abt '[] (HMeasure HProb)
+ Language.Hakaru.Syntax.Prelude: class Integrable (a :: Hakaru)
+ Language.Hakaru.Syntax.Prelude: class RealProb (a :: Hakaru)
+ Language.Hakaru.Syntax.Prelude: coerceTo_ :: (ABT Term abt) => Coercion a b -> abt '[] a -> abt '[] b
+ Language.Hakaru.Syntax.Prelude: cons :: (ABT Term abt, SingI a) => abt '[] a -> abt '[] (HList a) -> abt '[] (HList a)
+ Language.Hakaru.Syntax.Prelude: constV :: (ABT Term abt) => abt '[] HNat -> abt '[] b -> abt '[] (HArray b)
+ Language.Hakaru.Syntax.Prelude: cos :: (ABT Term abt) => abt '[] HReal -> abt '[] HReal
+ Language.Hakaru.Syntax.Prelude: cosh :: (ABT Term abt) => abt '[] HReal -> abt '[] HReal
+ Language.Hakaru.Syntax.Prelude: counting :: (ABT Term abt) => abt '[] (HMeasure HInt)
+ Language.Hakaru.Syntax.Prelude: datum_ :: (ABT Term abt) => Datum (abt '[]) (HData' t) -> abt '[] (HData' t)
+ Language.Hakaru.Syntax.Prelude: densityBeta :: (ABT Term abt) => abt '[] HProb -> abt '[] HProb -> abt '[] HProb -> abt '[] HProb
+ Language.Hakaru.Syntax.Prelude: densityCategorical :: (ABT Term abt) => abt '[] (HArray HProb) -> abt '[] HNat -> abt '[] HProb
+ Language.Hakaru.Syntax.Prelude: densityGamma :: (ABT Term abt) => abt '[] HProb -> abt '[] HProb -> abt '[] HProb -> abt '[] HProb
+ Language.Hakaru.Syntax.Prelude: densityNormal :: (ABT Term abt) => abt '[] HReal -> abt '[] HProb -> abt '[] HReal -> abt '[] HProb
+ Language.Hakaru.Syntax.Prelude: densityPoisson :: (ABT Term abt) => abt '[] HProb -> abt '[] HNat -> abt '[] HProb
+ Language.Hakaru.Syntax.Prelude: densityUniform :: (ABT Term abt) => abt '[] HReal -> abt '[] HReal -> abt '[] HReal -> abt '[] HProb
+ Language.Hakaru.Syntax.Prelude: dirac :: (ABT Term abt) => abt '[] a -> abt '[] (HMeasure a)
+ Language.Hakaru.Syntax.Prelude: dirichlet :: (ABT Term abt) => abt '[] (HArray HProb) -> abt '[] (HMeasure (HArray HProb))
+ Language.Hakaru.Syntax.Prelude: empty :: (ABT Term abt, SingI a) => abt '[] (HArray a)
+ Language.Hakaru.Syntax.Prelude: erf :: (RealProb a, ABT Term abt) => abt '[] a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: exp :: (RealProb a, ABT Term abt) => abt '[] a -> abt '[] HProb
+ Language.Hakaru.Syntax.Prelude: exponential :: (ABT Term abt) => abt '[] HProb -> abt '[] (HMeasure HProb)
+ Language.Hakaru.Syntax.Prelude: false :: (ABT Term abt) => abt '[] HBool
+ Language.Hakaru.Syntax.Prelude: fromInt :: (ABT Term abt) => abt '[] HInt -> abt '[] HReal
+ Language.Hakaru.Syntax.Prelude: fromProb :: (ABT Term abt) => abt '[] HProb -> abt '[] HReal
+ Language.Hakaru.Syntax.Prelude: fromRational :: forall abt a. (ABT Term abt, HFractional_ a) => Rational -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: fst :: (ABT Term abt) => abt '[] (HPair a b) -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: gamma :: (ABT Term abt) => abt '[] HProb -> abt '[] HProb -> abt '[] (HMeasure HProb)
+ Language.Hakaru.Syntax.Prelude: gamma' :: (ABT Term abt) => abt '[] HProb -> abt '[] HProb -> abt '[] (HMeasure HProb)
+ Language.Hakaru.Syntax.Prelude: gammaFunc :: (RealProb a, ABT Term abt) => abt '[] a -> abt '[] HProb
+ Language.Hakaru.Syntax.Prelude: geometric :: (ABT Term abt) => abt '[] HProb -> abt '[] (HMeasure HNat)
+ Language.Hakaru.Syntax.Prelude: guard :: (ABT Term abt) => abt '[] HBool -> abt '[] (HMeasure HUnit)
+ Language.Hakaru.Syntax.Prelude: half :: forall abt a. (ABT Term abt, HFractional_ a) => abt '[] a
+ Language.Hakaru.Syntax.Prelude: if_ :: (ABT Term abt) => abt '[] HBool -> abt '[] a -> abt '[] a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: infinity :: (Integrable a, ABT Term abt) => abt '[] a
+ Language.Hakaru.Syntax.Prelude: infix 4 >=
+ Language.Hakaru.Syntax.Prelude: infixl 1 >>
+ Language.Hakaru.Syntax.Prelude: infixl 4 *>
+ Language.Hakaru.Syntax.Prelude: infixl 6 -
+ Language.Hakaru.Syntax.Prelude: infixl 7 /
+ Language.Hakaru.Syntax.Prelude: infixl 9 !
+ Language.Hakaru.Syntax.Prelude: infixr 2 ||
+ Language.Hakaru.Syntax.Prelude: infixr 3 &&
+ Language.Hakaru.Syntax.Prelude: infixr 8 ^^
+ Language.Hakaru.Syntax.Prelude: instance Language.Hakaru.Syntax.Prelude.Integrable 'Language.Hakaru.Types.DataKind.HInt
+ Language.Hakaru.Syntax.Prelude: instance Language.Hakaru.Syntax.Prelude.Integrable 'Language.Hakaru.Types.DataKind.HNat
+ Language.Hakaru.Syntax.Prelude: instance Language.Hakaru.Syntax.Prelude.Integrable 'Language.Hakaru.Types.DataKind.HProb
+ Language.Hakaru.Syntax.Prelude: instance Language.Hakaru.Syntax.Prelude.Integrable 'Language.Hakaru.Types.DataKind.HReal
+ Language.Hakaru.Syntax.Prelude: instance Language.Hakaru.Syntax.Prelude.RealProb 'Language.Hakaru.Types.DataKind.HProb
+ Language.Hakaru.Syntax.Prelude: instance Language.Hakaru.Syntax.Prelude.RealProb 'Language.Hakaru.Types.DataKind.HReal
+ Language.Hakaru.Syntax.Prelude: int_ :: (ABT Term abt) => Integer -> abt '[] HInt
+ Language.Hakaru.Syntax.Prelude: integrate :: (ABT Term abt) => abt '[] HReal -> abt '[] HReal -> (abt '[] HReal -> abt '[] HProb) -> abt '[] HProb
+ Language.Hakaru.Syntax.Prelude: invgamma :: (ABT Term abt) => abt '[] HProb -> abt '[] HProb -> abt '[] (HMeasure HProb)
+ Language.Hakaru.Syntax.Prelude: just :: (ABT Term abt, SingI a) => abt '[] a -> abt '[] (HMaybe a)
+ Language.Hakaru.Syntax.Prelude: lam :: (ABT Term abt, SingI a) => (abt '[] a -> abt '[] b) -> abt '[] (a :-> b)
+ Language.Hakaru.Syntax.Prelude: lamWithVar :: (ABT Term abt) => Text -> Sing a -> (abt '[] a -> abt '[] b) -> abt '[] (a :-> b)
+ Language.Hakaru.Syntax.Prelude: laplace :: (ABT Term abt) => abt '[] HReal -> abt '[] HProb -> abt '[] (HMeasure HReal)
+ Language.Hakaru.Syntax.Prelude: lebesgue :: (ABT Term abt) => abt '[] (HMeasure HReal)
+ Language.Hakaru.Syntax.Prelude: left :: (ABT Term abt, SingI a, SingI b) => abt '[] a -> abt '[] (HEither a b)
+ Language.Hakaru.Syntax.Prelude: let_ :: (ABT Term abt) => abt '[] a -> (abt '[] a -> abt '[] b) -> abt '[] b
+ Language.Hakaru.Syntax.Prelude: liftM2 :: (ABT Term abt, SingI a, SingI b) => (abt '[] a -> abt '[] b -> abt '[] c) -> abt '[] (HMeasure a) -> abt '[] (HMeasure b) -> abt '[] (HMeasure c)
+ Language.Hakaru.Syntax.Prelude: list :: (ABT Term abt, SingI a) => [abt '[] a] -> abt '[] (HList a)
+ Language.Hakaru.Syntax.Prelude: literal_ :: (ABT Term abt) => Literal a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: log :: (ABT Term abt) => abt '[] HProb -> abt '[] HReal
+ Language.Hakaru.Syntax.Prelude: logBase :: (ABT Term abt) => abt '[] HProb -> abt '[] HProb -> abt '[] HReal
+ Language.Hakaru.Syntax.Prelude: mapV :: (ABT Term abt) => (abt '[] a -> abt '[] b) -> abt '[] (HArray a) -> abt '[] (HArray b)
+ Language.Hakaru.Syntax.Prelude: mapWithIndex :: (ABT Term abt) => (abt '[] HNat -> abt '[] a -> abt '[] b) -> abt '[] (HArray a) -> abt '[] (HArray b)
+ Language.Hakaru.Syntax.Prelude: max :: (ABT Term abt, HOrd_ a) => abt '[] a -> abt '[] a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: maximum :: (ABT Term abt, HOrd_ a) => [abt '[] a] -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: maybe :: (ABT Term abt, SingI a) => Maybe (abt '[] a) -> abt '[] (HMaybe a)
+ Language.Hakaru.Syntax.Prelude: measure0_ :: (ABT Term abt) => MeasureOp '[] a -> abt '[] (HMeasure a)
+ Language.Hakaru.Syntax.Prelude: measure1_ :: (ABT Term abt) => MeasureOp '[a] b -> abt '[] a -> abt '[] (HMeasure b)
+ Language.Hakaru.Syntax.Prelude: measure2_ :: (ABT Term abt) => MeasureOp '[a, b] c -> abt '[] a -> abt '[] b -> abt '[] (HMeasure c)
+ Language.Hakaru.Syntax.Prelude: memo :: MemoizedABT Term '[] a -> MemoizedABT Term '[] a
+ Language.Hakaru.Syntax.Prelude: min :: (ABT Term abt, HOrd_ a) => abt '[] a -> abt '[] a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: minimum :: (ABT Term abt, HOrd_ a) => [abt '[] a] -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: mix :: (ABT Term abt) => abt '[] (HArray HProb) -> abt '[] (HMeasure HNat)
+ Language.Hakaru.Syntax.Prelude: multinomial :: (ABT Term abt) => abt '[] HNat -> abt '[] (HArray HProb) -> abt '[] (HMeasure (HArray HProb))
+ Language.Hakaru.Syntax.Prelude: nand :: (ABT Term abt) => abt '[] HBool -> abt '[] HBool -> abt '[] HBool
+ Language.Hakaru.Syntax.Prelude: naryOp2_ :: (ABT Term abt) => NaryOp a -> abt '[] a -> abt '[] a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: naryOp_withIdentity :: (ABT Term abt) => NaryOp a -> abt '[] a -> [abt '[] a] -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: nat2int :: (ABT Term abt) => abt '[] HNat -> abt '[] HInt
+ Language.Hakaru.Syntax.Prelude: nat2prob :: (ABT Term abt) => abt '[] HNat -> abt '[] HProb
+ Language.Hakaru.Syntax.Prelude: nat2real :: (ABT Term abt) => abt '[] HNat -> abt '[] HReal
+ Language.Hakaru.Syntax.Prelude: nat_ :: (ABT Term abt) => Natural -> abt '[] HNat
+ Language.Hakaru.Syntax.Prelude: negate :: (ABT Term abt, HRing_ a) => abt '[] a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: negative :: (ABT Term abt, HRing_ a) => abt '[] (NonNegative a) -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: negativeBinomial :: (ABT Term abt) => abt '[] HNat -> abt '[] HProb -> abt '[] (HMeasure HNat)
+ Language.Hakaru.Syntax.Prelude: negativeInfinity :: (ABT Term abt, HRing_ a, Integrable a) => abt '[] a
+ Language.Hakaru.Syntax.Prelude: nil :: (ABT Term abt, SingI a) => abt '[] (HList a)
+ Language.Hakaru.Syntax.Prelude: nor :: (ABT Term abt) => abt '[] HBool -> abt '[] HBool -> abt '[] HBool
+ Language.Hakaru.Syntax.Prelude: normal :: (ABT Term abt) => abt '[] HReal -> abt '[] HProb -> abt '[] (HMeasure HReal)
+ Language.Hakaru.Syntax.Prelude: normal' :: (ABT Term abt) => abt '[] HReal -> abt '[] HProb -> abt '[] (HMeasure HReal)
+ Language.Hakaru.Syntax.Prelude: normalizeV :: (ABT Term abt) => abt '[] (HArray HProb) -> abt '[] (HArray HProb)
+ Language.Hakaru.Syntax.Prelude: not :: (ABT Term abt) => abt '[] HBool -> abt '[] HBool
+ Language.Hakaru.Syntax.Prelude: nothing :: (ABT Term abt, SingI a) => abt '[] (HMaybe a)
+ Language.Hakaru.Syntax.Prelude: one :: forall abt a. (ABT Term abt, HSemiring_ a) => abt '[] a
+ Language.Hakaru.Syntax.Prelude: one_ :: (ABT Term abt) => HSemiring a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: or :: (ABT Term abt) => [abt '[] HBool] -> abt '[] HBool
+ Language.Hakaru.Syntax.Prelude: pair :: (ABT Term abt, SingI a, SingI b) => abt '[] a -> abt '[] b -> abt '[] (HPair a b)
+ Language.Hakaru.Syntax.Prelude: pair_ :: (ABT Term abt) => Sing a -> Sing b -> abt '[] a -> abt '[] b -> abt '[] (HPair a b)
+ Language.Hakaru.Syntax.Prelude: pi :: (RealProb a, ABT Term abt) => abt '[] a
+ Language.Hakaru.Syntax.Prelude: plate :: (ABT Term abt) => abt '[] HNat -> (abt '[] HNat -> abt '[] (HMeasure a)) -> abt '[] (HMeasure (HArray a))
+ Language.Hakaru.Syntax.Prelude: plate' :: (ABT Term abt, SingI a) => abt '[] (HArray (HMeasure a)) -> abt '[] (HMeasure (HArray a))
+ Language.Hakaru.Syntax.Prelude: plateWithVar :: (ABT Term abt) => abt '[] HNat -> Variable HNat -> abt '[] (HMeasure a) -> abt '[] (HMeasure (HArray a))
+ Language.Hakaru.Syntax.Prelude: poisson :: (ABT Term abt) => abt '[] HProb -> abt '[] (HMeasure HNat)
+ Language.Hakaru.Syntax.Prelude: poisson' :: (ABT Term abt) => abt '[] HProb -> abt '[] (HMeasure HNat)
+ Language.Hakaru.Syntax.Prelude: primOp0_ :: (ABT Term abt) => PrimOp '[] a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: primOp1_ :: (ABT Term abt) => PrimOp '[a] b -> abt '[] a -> abt '[] b
+ Language.Hakaru.Syntax.Prelude: primOp2_ :: (ABT Term abt) => PrimOp '[a, b] c -> abt '[] a -> abt '[] b -> abt '[] c
+ Language.Hakaru.Syntax.Prelude: primOp3_ :: (ABT Term abt) => PrimOp '[a, b, c] d -> abt '[] a -> abt '[] b -> abt '[] c -> abt '[] d
+ Language.Hakaru.Syntax.Prelude: prob_ :: (ABT Term abt) => NonNegativeRational -> abt '[] HProb
+ Language.Hakaru.Syntax.Prelude: prod :: (ABT Term abt, HSemiring_ a) => [abt '[] a] -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: product :: (ABT Term abt, HDiscrete_ a, HSemiring_ b, SingI a) => abt '[] a -> abt '[] a -> (abt '[] a -> abt '[] b) -> abt '[] b
+ Language.Hakaru.Syntax.Prelude: real_ :: (ABT Term abt) => Rational -> abt '[] HReal
+ Language.Hakaru.Syntax.Prelude: recip :: (ABT Term abt, HFractional_ a) => abt '[] a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: reduce :: (ABT Term abt) => (abt '[] a -> abt '[] a -> abt '[] a) -> abt '[] a -> abt '[] (HArray a) -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: reject :: (ABT Term abt) => (Sing (HMeasure a)) -> abt '[] (HMeasure a)
+ Language.Hakaru.Syntax.Prelude: right :: (ABT Term abt, SingI a, SingI b) => abt '[] b -> abt '[] (HEither a b)
+ Language.Hakaru.Syntax.Prelude: signum :: (ABT Term abt, HRing_ a) => abt '[] a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: sin :: (ABT Term abt) => abt '[] HReal -> abt '[] HReal
+ Language.Hakaru.Syntax.Prelude: sinh :: (ABT Term abt) => abt '[] HReal -> abt '[] HReal
+ Language.Hakaru.Syntax.Prelude: size :: (ABT Term abt) => abt '[] (HArray a) -> abt '[] HNat
+ Language.Hakaru.Syntax.Prelude: snd :: (ABT Term abt) => abt '[] (HPair a b) -> abt '[] b
+ Language.Hakaru.Syntax.Prelude: sqrt :: (ABT Term abt, HRadical_ a) => abt '[] a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: square :: (ABT Term abt, HRing_ a) => abt '[] a -> abt '[] (NonNegative a)
+ Language.Hakaru.Syntax.Prelude: studentT :: (ABT Term abt) => abt '[] HReal -> abt '[] HProb -> abt '[] HProb -> abt '[] (HMeasure HReal)
+ Language.Hakaru.Syntax.Prelude: sum :: (ABT Term abt, HSemiring_ a) => [abt '[] a] -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: sumV :: (ABT Term abt, HSemiring_ a) => abt '[] (HArray a) -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: summate :: (ABT Term abt, HDiscrete_ a, HSemiring_ b, SingI a) => abt '[] a -> abt '[] a -> (abt '[] a -> abt '[] b) -> abt '[] b
+ Language.Hakaru.Syntax.Prelude: summateV :: (ABT Term abt) => abt '[] (HArray HProb) -> abt '[] HProb
+ Language.Hakaru.Syntax.Prelude: superpose :: (ABT Term abt) => NonEmpty (abt '[] HProb, abt '[] (HMeasure a)) -> abt '[] (HMeasure a)
+ Language.Hakaru.Syntax.Prelude: swap :: (ABT Term abt, SingI a, SingI b) => abt '[] (HPair a b) -> abt '[] (HPair b a)
+ Language.Hakaru.Syntax.Prelude: tan :: (ABT Term abt) => abt '[] HReal -> abt '[] HReal
+ Language.Hakaru.Syntax.Prelude: tanh :: (ABT Term abt) => abt '[] HReal -> abt '[] HReal
+ Language.Hakaru.Syntax.Prelude: thRootOf :: (ABT Term abt, HRadical_ a) => abt '[] HNat -> abt '[] a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: third :: (ABT Term abt, HFractional_ a) => abt '[] a
+ Language.Hakaru.Syntax.Prelude: triv :: TrivialABT Term '[] a -> TrivialABT Term '[] a
+ Language.Hakaru.Syntax.Prelude: true :: (ABT Term abt) => abt '[] HBool
+ Language.Hakaru.Syntax.Prelude: uneither :: (ABT Term abt) => abt '[] (HEither a b) -> (abt '[] a -> abt '[] c) -> (abt '[] b -> abt '[] c) -> abt '[] c
+ Language.Hakaru.Syntax.Prelude: uniform :: (ABT Term abt) => abt '[] HReal -> abt '[] HReal -> abt '[] (HMeasure HReal)
+ Language.Hakaru.Syntax.Prelude: uniform' :: (ABT Term abt) => abt '[] HReal -> abt '[] HReal -> abt '[] (HMeasure HReal)
+ Language.Hakaru.Syntax.Prelude: unit :: (ABT Term abt) => abt '[] HUnit
+ Language.Hakaru.Syntax.Prelude: unitV :: (ABT Term abt) => abt '[] HNat -> abt '[] HNat -> abt '[] (HArray HProb)
+ Language.Hakaru.Syntax.Prelude: unmaybe :: (ABT Term abt) => abt '[] (HMaybe a) -> abt '[] b -> (abt '[] a -> abt '[] b) -> abt '[] b
+ Language.Hakaru.Syntax.Prelude: unpair :: forall abt a b c. (ABT Term abt) => abt '[] (HPair a b) -> (abt '[] a -> abt '[] b -> abt '[] c) -> abt '[] c
+ Language.Hakaru.Syntax.Prelude: unsafeDiv :: (ABT Term abt, HSemiring_ a) => abt '[] a -> abt '[] a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: unsafeDiv_ :: (ABT Term abt) => HSemiring a -> abt '[] a -> abt '[] a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: unsafeFrom_ :: (ABT Term abt) => Coercion a b -> abt '[] b -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: unsafeMinus :: (ABT Term abt, HSemiring_ a) => abt '[] a -> abt '[] a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: unsafeMinusNat :: (ABT Term abt) => abt '[] HNat -> abt '[] HNat -> abt '[] HNat
+ Language.Hakaru.Syntax.Prelude: unsafeMinusProb :: (ABT Term abt) => abt '[] HProb -> abt '[] HProb -> abt '[] HProb
+ Language.Hakaru.Syntax.Prelude: unsafeMinus_ :: (ABT Term abt) => HSemiring a -> abt '[] a -> abt '[] a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: unsafeNaryOp_ :: (ABT Term abt) => NaryOp a -> [abt '[] a] -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: unsafeProb :: (ABT Term abt) => abt '[] HReal -> abt '[] HProb
+ Language.Hakaru.Syntax.Prelude: unsafeProbFraction :: forall abt a. (ABT Term abt, HFractional_ a) => abt '[] a -> abt '[] HProb
+ Language.Hakaru.Syntax.Prelude: unsafeProbFraction_ :: (ABT Term abt) => HFractional a -> abt '[] a -> abt '[] HProb
+ Language.Hakaru.Syntax.Prelude: unsafeProbSemiring :: forall abt a. (ABT Term abt, HSemiring_ a) => abt '[] a -> abt '[] HProb
+ Language.Hakaru.Syntax.Prelude: unsafeProbSemiring_ :: (ABT Term abt) => HSemiring a -> abt '[] a -> abt '[] HProb
+ Language.Hakaru.Syntax.Prelude: weibull :: (ABT Term abt) => abt '[] HProb -> abt '[] HProb -> abt '[] (HMeasure HProb)
+ Language.Hakaru.Syntax.Prelude: weight :: (ABT Term abt) => abt '[] HProb -> abt '[] (HMeasure HUnit)
+ Language.Hakaru.Syntax.Prelude: weightedDirac :: (ABT Term abt, SingI a) => abt '[] a -> abt '[] HProb -> abt '[] (HMeasure a)
+ Language.Hakaru.Syntax.Prelude: withGuard :: (ABT Term abt) => abt '[] HBool -> abt '[] (HMeasure a) -> abt '[] (HMeasure a)
+ Language.Hakaru.Syntax.Prelude: withWeight :: (ABT Term abt) => abt '[] HProb -> abt '[] (HMeasure w) -> abt '[] (HMeasure w)
+ Language.Hakaru.Syntax.Prelude: zero :: forall abt a. (ABT Term abt, HSemiring_ a) => abt '[] a
+ Language.Hakaru.Syntax.Prelude: zero_ :: (ABT Term abt) => HSemiring a -> abt '[] a
+ Language.Hakaru.Syntax.Prelude: zipWithV :: (ABT Term abt) => (abt '[] a -> abt '[] b -> abt '[] c) -> abt '[] (HArray a) -> abt '[] (HArray b) -> abt '[] (HArray c)
+ Language.Hakaru.Syntax.TypeCheck: LaxMode :: TypeCheckMode
+ Language.Hakaru.Syntax.TypeCheck: StrictMode :: TypeCheckMode
+ Language.Hakaru.Syntax.TypeCheck: TypedAST :: !(Sing b) -> !(abt '[] b) -> TypedAST
+ Language.Hakaru.Syntax.TypeCheck: UnsafeMode :: TypeCheckMode
+ Language.Hakaru.Syntax.TypeCheck: checkType :: forall abt a. (ABT Term abt) => Sing a -> AST -> TypeCheckMonad (abt '[] a)
+ Language.Hakaru.Syntax.TypeCheck: data TypeCheckMode
+ Language.Hakaru.Syntax.TypeCheck: data TypeCheckMonad a
+ Language.Hakaru.Syntax.TypeCheck: data TypedAST (abt :: [Hakaru] -> Hakaru -> *)
+ Language.Hakaru.Syntax.TypeCheck: inferType :: forall abt. (ABT Term abt) => AST -> TypeCheckMonad (TypedAST abt)
+ Language.Hakaru.Syntax.TypeCheck: inferable :: AST -> Bool
+ Language.Hakaru.Syntax.TypeCheck: instance GHC.Base.Applicative Language.Hakaru.Syntax.TypeCheck.TypeCheckMonad
+ Language.Hakaru.Syntax.TypeCheck: instance GHC.Base.Functor Language.Hakaru.Syntax.TypeCheck.TypeCheckMonad
+ Language.Hakaru.Syntax.TypeCheck: instance GHC.Base.Monad Language.Hakaru.Syntax.TypeCheck.TypeCheckMonad
+ Language.Hakaru.Syntax.TypeCheck: instance GHC.Read.Read Language.Hakaru.Syntax.TypeCheck.TypeCheckMode
+ Language.Hakaru.Syntax.TypeCheck: instance GHC.Show.Show Language.Hakaru.Syntax.TypeCheck.TypeCheckMode
+ Language.Hakaru.Syntax.TypeCheck: instance Language.Hakaru.Syntax.ABT.ABT Language.Hakaru.Syntax.AST.Term abt => Language.Hakaru.Types.Coercion.Coerce (Language.Hakaru.Syntax.Datum.Branch a abt)
+ Language.Hakaru.Syntax.TypeCheck: instance Language.Hakaru.Syntax.IClasses.Show2 abt => GHC.Show.Show (Language.Hakaru.Syntax.TypeCheck.TypedAST abt)
+ Language.Hakaru.Syntax.TypeCheck: mustCheck :: AST -> Bool
+ Language.Hakaru.Syntax.TypeCheck: runTCM :: TypeCheckMonad a -> Input -> TypeCheckMode -> Either TypeCheckError a
+ Language.Hakaru.Syntax.TypeCheck: type TypeCheckError = Text
+ Language.Hakaru.Syntax.TypeCheck: unTCM :: TypeCheckMonad a -> Ctx -> Input -> TypeCheckMode -> Either TypeCheckError a
+ Language.Hakaru.Syntax.TypeOf: getTermSing :: forall abt r. (ABT Term abt) => (forall xs a. r xs a -> Either String (Sing a)) -> forall a. Term (Pair2 abt r) a -> Either String (Sing a)
+ Language.Hakaru.Syntax.TypeOf: typeOf :: (ABT Term abt) => abt '[] a -> Sing a
+ Language.Hakaru.Syntax.Value: [VArray] :: {-# UNPACK #-} !(Vector (Value a)) -> Value (HArray a)
+ Language.Hakaru.Syntax.Value: [VDatum] :: !(Datum Value (HData' t)) -> Value (HData' t)
+ Language.Hakaru.Syntax.Value: [VInt] :: {-# UNPACK #-} !Int -> Value HInt
+ Language.Hakaru.Syntax.Value: [VLam] :: (Value a -> Value b) -> Value (a :-> b)
+ Language.Hakaru.Syntax.Value: [VMeasure] :: (Value HProb -> GenIO -> IO (Maybe (Value a, Value HProb))) -> Value (HMeasure a)
+ Language.Hakaru.Syntax.Value: [VNat] :: {-# UNPACK #-} !Nat -> Value HNat
+ Language.Hakaru.Syntax.Value: [VProb] :: {-# UNPACK #-} !LogFloat -> Value HProb
+ Language.Hakaru.Syntax.Value: [VReal] :: {-# UNPACK #-} !Double -> Value HReal
+ Language.Hakaru.Syntax.Value: data Value :: Hakaru -> *
+ Language.Hakaru.Syntax.Value: enumFromUntilValue :: (HDiscrete a) -> Value a -> Value a -> [Value a]
+ Language.Hakaru.Syntax.Value: instance GHC.Classes.Eq (Language.Hakaru.Syntax.Value.Value a)
+ Language.Hakaru.Syntax.Value: instance GHC.Show.Show (Language.Hakaru.Syntax.Value.Value a)
+ Language.Hakaru.Syntax.Value: instance Language.Hakaru.Syntax.IClasses.Eq1 Language.Hakaru.Syntax.Value.Value
+ Language.Hakaru.Syntax.Value: instance Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Syntax.Value.Value
+ Language.Hakaru.Syntax.Value: instance Language.Hakaru.Types.Coercion.Coerce Language.Hakaru.Syntax.Value.Value
+ Language.Hakaru.Syntax.Value: instance Language.Hakaru.Types.Coercion.PrimCoerce Language.Hakaru.Syntax.Value.Value
+ Language.Hakaru.Syntax.Value: lam2 :: Value (a :-> (b :-> c)) -> (Value a -> Value b -> Value c)
+ Language.Hakaru.Syntax.Variable: Assoc :: {-# UNPACK #-} !(Variable a) -> !(ast a) -> Assoc
+ Language.Hakaru.Syntax.Variable: Assocs :: IntMap (Assoc ast) -> Assocs ast
+ Language.Hakaru.Syntax.Variable: SomeVariable :: {-# UNPACK #-} !(Variable (a :: k)) -> SomeVariable
+ Language.Hakaru.Syntax.Variable: VarSet :: IntMap (SomeVariable kproxy) -> VarSet
+ Language.Hakaru.Syntax.Variable: Variable :: {-# UNPACK #-} !Text -> Nat -> !(Sing a) -> Variable
+ Language.Hakaru.Syntax.Variable: [VarEqTypeError] :: (Show1 (Sing :: k -> *), JmEq1 (Sing :: k -> *)) => {-# UNPACK #-} !(Variable (a :: k)) -> {-# UNPACK #-} !(Variable (b :: k)) -> VarEqTypeError
+ Language.Hakaru.Syntax.Variable: [unAssocs] :: Assocs ast -> IntMap (Assoc ast)
+ Language.Hakaru.Syntax.Variable: [unVarSet] :: VarSet -> IntMap (SomeVariable kproxy)
+ Language.Hakaru.Syntax.Variable: [varHint] :: Variable -> {-# UNPACK #-} !Text
+ Language.Hakaru.Syntax.Variable: [varID] :: Variable -> Nat
+ Language.Hakaru.Syntax.Variable: [varType] :: Variable -> !(Sing a)
+ Language.Hakaru.Syntax.Variable: adjustAssoc :: Variable (a :: k) -> (Assoc ast -> Assoc ast) -> Assocs ast -> Assocs ast
+ Language.Hakaru.Syntax.Variable: data Assoc (ast :: k -> *)
+ Language.Hakaru.Syntax.Variable: data SomeVariable (kproxy :: KProxy k)
+ Language.Hakaru.Syntax.Variable: data VarEqTypeError
+ Language.Hakaru.Syntax.Variable: data Variable (a :: k)
+ Language.Hakaru.Syntax.Variable: deleteVarSet :: Variable a -> VarSet (KindOf a) -> VarSet (KindOf a)
+ Language.Hakaru.Syntax.Variable: emptyAssocs :: Assocs abt
+ Language.Hakaru.Syntax.Variable: emptyVarSet :: VarSet kproxy
+ Language.Hakaru.Syntax.Variable: fromAssocs :: Assocs ast -> [Assoc ast]
+ Language.Hakaru.Syntax.Variable: fromVarSet :: VarSet kproxy -> [SomeVariable kproxy]
+ Language.Hakaru.Syntax.Variable: insertAssoc :: Assoc ast -> Assocs ast -> Assocs ast
+ Language.Hakaru.Syntax.Variable: insertAssocs :: Assocs ast -> Assocs ast -> Assocs ast
+ Language.Hakaru.Syntax.Variable: insertVarSet :: Variable a -> VarSet (KindOf a) -> VarSet (KindOf a)
+ Language.Hakaru.Syntax.Variable: instance GHC.Exception.Exception Language.Hakaru.Syntax.Variable.VarEqTypeError
+ Language.Hakaru.Syntax.Variable: instance GHC.Show.Show Language.Hakaru.Syntax.Variable.VarEqTypeError
+ Language.Hakaru.Syntax.Variable: instance Language.Hakaru.Syntax.IClasses.Eq1 Language.Hakaru.Syntax.Variable.Variable
+ Language.Hakaru.Syntax.Variable: instance Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing => Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Syntax.Variable.Variable
+ Language.Hakaru.Syntax.Variable: instance forall k (a :: k). GHC.Classes.Eq (Language.Hakaru.Syntax.Variable.Variable a)
+ Language.Hakaru.Syntax.Variable: instance forall k (a :: k). GHC.Classes.Ord (Language.Hakaru.Syntax.Variable.Variable a)
+ Language.Hakaru.Syntax.Variable: instance forall k (a :: k). GHC.Show.Show (Language.Hakaru.Types.Sing.Sing a) => GHC.Show.Show (Language.Hakaru.Syntax.Variable.Variable a)
+ Language.Hakaru.Syntax.Variable: instance forall k (abt :: k -> GHC.Types.*). GHC.Base.Monoid (Language.Hakaru.Syntax.Variable.Assocs abt)
+ Language.Hakaru.Syntax.Variable: instance forall k (ast :: k -> GHC.Types.*). (Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Show1 ast) => GHC.Show.Show (Language.Hakaru.Syntax.Variable.Assoc ast)
+ Language.Hakaru.Syntax.Variable: instance forall k (ast :: k -> GHC.Types.*). (Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Show1 ast) => GHC.Show.Show (Language.Hakaru.Syntax.Variable.Assocs ast)
+ Language.Hakaru.Syntax.Variable: instance forall k (kproxy :: Data.Proxy.KProxy k). (Language.Hakaru.Syntax.IClasses.JmEq1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing) => GHC.Classes.Eq (Language.Hakaru.Syntax.Variable.SomeVariable kproxy)
+ Language.Hakaru.Syntax.Variable: instance forall k (kproxy :: Data.Proxy.KProxy k). (Language.Hakaru.Syntax.IClasses.JmEq1 Language.Hakaru.Types.Sing.Sing, Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing) => GHC.Classes.Ord (Language.Hakaru.Syntax.Variable.SomeVariable kproxy)
+ Language.Hakaru.Syntax.Variable: instance forall k (kproxy :: Data.Proxy.KProxy k). GHC.Base.Monoid (Language.Hakaru.Syntax.Variable.VarSet kproxy)
+ Language.Hakaru.Syntax.Variable: instance forall k (kproxy :: Data.Proxy.KProxy k). Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing => GHC.Show.Show (Language.Hakaru.Syntax.Variable.SomeVariable kproxy)
+ Language.Hakaru.Syntax.Variable: instance forall k (kproxy :: Data.Proxy.KProxy k). Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing => GHC.Show.Show (Language.Hakaru.Syntax.Variable.VarSet kproxy)
+ Language.Hakaru.Syntax.Variable: lookupAssoc :: (Show1 (Sing :: k -> *), JmEq1 (Sing :: k -> *)) => Variable (a :: k) -> Assocs ast -> Maybe (ast a)
+ Language.Hakaru.Syntax.Variable: mapAssocs :: (Assoc ast1 -> Assoc ast2) -> Assocs ast1 -> Assocs ast2
+ Language.Hakaru.Syntax.Variable: memberVarSet :: (Show1 (Sing :: k -> *), JmEq1 (Sing :: k -> *)) => Variable (a :: k) -> VarSet (kproxy :: KProxy k) -> Bool
+ Language.Hakaru.Syntax.Variable: newtype Assocs ast
+ Language.Hakaru.Syntax.Variable: newtype VarSet (kproxy :: KProxy k)
+ Language.Hakaru.Syntax.Variable: nextVarID :: VarSet kproxy -> Nat
+ Language.Hakaru.Syntax.Variable: singletonAssocs :: Variable a -> f a -> Assocs f
+ Language.Hakaru.Syntax.Variable: singletonVarSet :: Variable a -> VarSet (KindOf a)
+ Language.Hakaru.Syntax.Variable: toAssocs :: [Assoc ast] -> Assocs ast
+ Language.Hakaru.Syntax.Variable: toAssocs1 :: List1 Variable xs -> List1 ast xs -> Assocs ast
+ Language.Hakaru.Syntax.Variable: toVarSet :: [SomeVariable kproxy] -> VarSet kproxy
+ Language.Hakaru.Syntax.Variable: toVarSet1 :: List1 Variable (xs :: [k]) -> VarSet (kproxy :: KProxy k)
+ Language.Hakaru.Syntax.Variable: type KindOf (a :: k) = (KProxy :: KProxy k)
+ Language.Hakaru.Syntax.Variable: varEq :: (Show1 (Sing :: k -> *), JmEq1 (Sing :: k -> *)) => Variable (a :: k) -> Variable (b :: k) -> Maybe (TypeEq a b)
+ Language.Hakaru.Types.Coercion: Lub :: !(Sing c) -> !(Coercion a c) -> !(Coercion b c) -> Lub
+ Language.Hakaru.Types.Coercion: Mixed :: (Sing c, Coercion c a, Coercion c b) -> CoercionMode a b
+ Language.Hakaru.Types.Coercion: Safe :: (Coercion a b) -> CoercionMode a b
+ Language.Hakaru.Types.Coercion: SomeFractional :: !(HFractional b) -> !(Coercion a b) -> SomeFractional
+ Language.Hakaru.Types.Coercion: SomeRing :: !(HRing b) -> !(Coercion a b) -> SomeRing
+ Language.Hakaru.Types.Coercion: Unsafe :: (Coercion b a) -> CoercionMode a b
+ Language.Hakaru.Types.Coercion: [CCons] :: !(PrimCoercion a b) -> !(Coercion b c) -> Coercion a c
+ Language.Hakaru.Types.Coercion: [CNil] :: Coercion a a
+ Language.Hakaru.Types.Coercion: [Continuous] :: !(HContinuous a) -> PrimCoercion (HIntegral a) a
+ Language.Hakaru.Types.Coercion: [Signed] :: !(HRing a) -> PrimCoercion (NonNegative a) a
+ Language.Hakaru.Types.Coercion: [ZRefl] :: ZigZag a a
+ Language.Hakaru.Types.Coercion: [Zag] :: !(Coercion b a) -> !(ZigZag b c) -> ZigZag a c
+ Language.Hakaru.Types.Coercion: [Zig] :: !(Coercion a b) -> !(ZigZag b c) -> ZigZag a c
+ Language.Hakaru.Types.Coercion: class Coerce (f :: Hakaru -> *)
+ Language.Hakaru.Types.Coercion: class PrimCoerce (f :: Hakaru -> *)
+ Language.Hakaru.Types.Coercion: coerceFrom :: Coerce f => Coercion a b -> f b -> f a
+ Language.Hakaru.Types.Coercion: coerceTo :: Coerce f => Coercion a b -> f a -> f b
+ Language.Hakaru.Types.Coercion: continuous :: (HContinuous_ a) => Coercion (HIntegral a) a
+ Language.Hakaru.Types.Coercion: data Coercion :: Hakaru -> Hakaru -> *
+ Language.Hakaru.Types.Coercion: data CoercionMode a b
+ Language.Hakaru.Types.Coercion: data Lub (a :: Hakaru) (b :: Hakaru)
+ Language.Hakaru.Types.Coercion: data PrimCoercion :: Hakaru -> Hakaru -> *
+ Language.Hakaru.Types.Coercion: data SomeFractional (a :: Hakaru)
+ Language.Hakaru.Types.Coercion: data SomeRing (a :: Hakaru)
+ Language.Hakaru.Types.Coercion: data ZigZag :: Hakaru -> Hakaru -> *
+ Language.Hakaru.Types.Coercion: findCoercion :: Sing a -> Sing b -> Maybe (Coercion a b)
+ Language.Hakaru.Types.Coercion: findEitherCoercion :: Sing a -> Sing b -> Maybe (CoercionMode a b)
+ Language.Hakaru.Types.Coercion: findFractional :: Sing a -> Maybe (SomeFractional a)
+ Language.Hakaru.Types.Coercion: findLub :: Sing a -> Sing b -> Maybe (Lub a b)
+ Language.Hakaru.Types.Coercion: findRing :: Sing a -> Maybe (SomeRing a)
+ Language.Hakaru.Types.Coercion: instance Control.Category.Category Language.Hakaru.Types.Coercion.Coercion
+ Language.Hakaru.Types.Coercion: instance Control.Category.Category Language.Hakaru.Types.Coercion.RevCoercion
+ Language.Hakaru.Types.Coercion: instance GHC.Classes.Eq (Language.Hakaru.Types.Coercion.Coercion a b)
+ Language.Hakaru.Types.Coercion: instance GHC.Classes.Eq (Language.Hakaru.Types.Coercion.PrimCoercion a b)
+ Language.Hakaru.Types.Coercion: instance GHC.Show.Show (Language.Hakaru.Types.Coercion.CoerceTo_UnsafeFrom a b)
+ Language.Hakaru.Types.Coercion: instance GHC.Show.Show (Language.Hakaru.Types.Coercion.Coercion a b)
+ Language.Hakaru.Types.Coercion: instance GHC.Show.Show (Language.Hakaru.Types.Coercion.PrimCoercion a b)
+ Language.Hakaru.Types.Coercion: instance GHC.Show.Show (Language.Hakaru.Types.Coercion.RevCoercion a b)
+ Language.Hakaru.Types.Coercion: instance GHC.Show.Show (Language.Hakaru.Types.Coercion.UnsafeFrom_CoerceTo a b)
+ Language.Hakaru.Types.Coercion: instance GHC.Show.Show (Language.Hakaru.Types.Coercion.ZigZag a b)
+ Language.Hakaru.Types.Coercion: instance Language.Hakaru.Syntax.IClasses.Eq1 (Language.Hakaru.Types.Coercion.Coercion a)
+ Language.Hakaru.Types.Coercion: instance Language.Hakaru.Syntax.IClasses.Eq1 (Language.Hakaru.Types.Coercion.PrimCoercion a)
+ Language.Hakaru.Types.Coercion: instance Language.Hakaru.Syntax.IClasses.Eq2 Language.Hakaru.Types.Coercion.Coercion
+ Language.Hakaru.Types.Coercion: instance Language.Hakaru.Syntax.IClasses.Eq2 Language.Hakaru.Types.Coercion.PrimCoercion
+ Language.Hakaru.Types.Coercion: instance Language.Hakaru.Syntax.IClasses.JmEq1 (Language.Hakaru.Types.Coercion.PrimCoercion a)
+ Language.Hakaru.Types.Coercion: instance Language.Hakaru.Syntax.IClasses.JmEq2 Language.Hakaru.Types.Coercion.PrimCoercion
+ Language.Hakaru.Types.Coercion: instance Language.Hakaru.Types.Coercion.Coerce Language.Hakaru.Types.Sing.Sing
+ Language.Hakaru.Types.Coercion: instance Language.Hakaru.Types.Coercion.PrimCoerce Language.Hakaru.Types.Sing.Sing
+ Language.Hakaru.Types.Coercion: primCoerceFrom :: PrimCoerce f => PrimCoercion a b -> f b -> f a
+ Language.Hakaru.Types.Coercion: primCoerceTo :: PrimCoerce f => PrimCoercion a b -> f a -> f b
+ Language.Hakaru.Types.Coercion: signed :: (HRing_ a) => Coercion (NonNegative a) a
+ Language.Hakaru.Types.Coercion: simplifyZZ :: ZigZag a b -> ZigZag a b
+ Language.Hakaru.Types.Coercion: singCoerceCod :: Coercion a b -> Maybe (Sing b)
+ Language.Hakaru.Types.Coercion: singCoerceDom :: Coercion a b -> Maybe (Sing a)
+ Language.Hakaru.Types.Coercion: singCoerceDomCod :: Coercion a b -> Maybe (Sing a, Sing b)
+ Language.Hakaru.Types.Coercion: singletonCoercion :: PrimCoercion a b -> Coercion a b
+ Language.Hakaru.Types.DataKind: (:->) :: !Hakaru -> !Hakaru -> Hakaru
+ Language.Hakaru.Types.DataKind: (:@) :: HakaruCon -> Hakaru -> HakaruCon
+ Language.Hakaru.Types.DataKind: HArray :: !Hakaru -> Hakaru
+ Language.Hakaru.Types.DataKind: HData :: !HakaruCon -> [[HakaruFun]] -> Hakaru
+ Language.Hakaru.Types.DataKind: HInt :: Hakaru
+ Language.Hakaru.Types.DataKind: HMeasure :: !Hakaru -> Hakaru
+ Language.Hakaru.Types.DataKind: HNat :: Hakaru
+ Language.Hakaru.Types.DataKind: HProb :: Hakaru
+ Language.Hakaru.Types.DataKind: HReal :: Hakaru
+ Language.Hakaru.Types.DataKind: I :: HakaruFun
+ Language.Hakaru.Types.DataKind: K :: !Hakaru -> HakaruFun
+ Language.Hakaru.Types.DataKind: TyCon :: !Symbol -> HakaruCon
+ Language.Hakaru.Types.DataKind: data Hakaru
+ Language.Hakaru.Types.DataKind: data HakaruCon
+ Language.Hakaru.Types.DataKind: data HakaruFun
+ Language.Hakaru.Types.DataKind: data Symbol :: *
+ Language.Hakaru.Types.DataKind: type HBool = HData (TyCon "Bool") '['[], '[]]
+ Language.Hakaru.Types.DataKind: type HData' t = HData t (Code t)
+ Language.Hakaru.Types.DataKind: type HEither a b = HData ((TyCon "Either" :@ a) :@ b) '['[K a], '[K b]]
+ Language.Hakaru.Types.DataKind: type HList a = HData (TyCon "List" :@ a) '['[], '[K a, I]]
+ Language.Hakaru.Types.DataKind: type HMaybe a = HData (TyCon "Maybe" :@ a) '['[], '[K a]]
+ Language.Hakaru.Types.DataKind: type HPair a b = HData ((TyCon "Pair" :@ a) :@ b) '['[K a, K b]]
+ Language.Hakaru.Types.DataKind: type HUnit = HData (TyCon "Unit") '['[]]
+ Language.Hakaru.Types.HClasses: [HContinuous_Prob] :: HContinuous HProb
+ Language.Hakaru.Types.HClasses: [HContinuous_Real] :: HContinuous HReal
+ Language.Hakaru.Types.HClasses: [HDiscrete_Int] :: HDiscrete HInt
+ Language.Hakaru.Types.HClasses: [HDiscrete_Nat] :: HDiscrete HNat
+ Language.Hakaru.Types.HClasses: [HEq_Array] :: !(HEq a) -> HEq (HArray a)
+ Language.Hakaru.Types.HClasses: [HEq_Bool] :: HEq HBool
+ Language.Hakaru.Types.HClasses: [HEq_Either] :: !(HEq a) -> !(HEq b) -> HEq (HEither a b)
+ Language.Hakaru.Types.HClasses: [HEq_Int] :: HEq HInt
+ Language.Hakaru.Types.HClasses: [HEq_Nat] :: HEq HNat
+ Language.Hakaru.Types.HClasses: [HEq_Pair] :: !(HEq a) -> !(HEq b) -> HEq (HPair a b)
+ Language.Hakaru.Types.HClasses: [HEq_Prob] :: HEq HProb
+ Language.Hakaru.Types.HClasses: [HEq_Real] :: HEq HReal
+ Language.Hakaru.Types.HClasses: [HEq_Unit] :: HEq HUnit
+ Language.Hakaru.Types.HClasses: [HFractional_Prob] :: HFractional HProb
+ Language.Hakaru.Types.HClasses: [HFractional_Real] :: HFractional HReal
+ Language.Hakaru.Types.HClasses: [HIntegrable_Nat] :: HIntegrable HNat
+ Language.Hakaru.Types.HClasses: [HIntegrable_Prob] :: HIntegrable HProb
+ Language.Hakaru.Types.HClasses: [HOrd_Array] :: !(HOrd a) -> HOrd (HArray a)
+ Language.Hakaru.Types.HClasses: [HOrd_Bool] :: HOrd HBool
+ Language.Hakaru.Types.HClasses: [HOrd_Either] :: !(HOrd a) -> !(HOrd b) -> HOrd (HEither a b)
+ Language.Hakaru.Types.HClasses: [HOrd_Int] :: HOrd HInt
+ Language.Hakaru.Types.HClasses: [HOrd_Nat] :: HOrd HNat
+ Language.Hakaru.Types.HClasses: [HOrd_Pair] :: !(HOrd a) -> !(HOrd b) -> HOrd (HPair a b)
+ Language.Hakaru.Types.HClasses: [HOrd_Prob] :: HOrd HProb
+ Language.Hakaru.Types.HClasses: [HOrd_Real] :: HOrd HReal
+ Language.Hakaru.Types.HClasses: [HOrd_Unit] :: HOrd HUnit
+ Language.Hakaru.Types.HClasses: [HRadical_Prob] :: HRadical HProb
+ Language.Hakaru.Types.HClasses: [HRing_Int] :: HRing HInt
+ Language.Hakaru.Types.HClasses: [HRing_Real] :: HRing HReal
+ Language.Hakaru.Types.HClasses: [HSemiring_Int] :: HSemiring HInt
+ Language.Hakaru.Types.HClasses: [HSemiring_Nat] :: HSemiring HNat
+ Language.Hakaru.Types.HClasses: [HSemiring_Prob] :: HSemiring HProb
+ Language.Hakaru.Types.HClasses: [HSemiring_Real] :: HSemiring HReal
+ Language.Hakaru.Types.HClasses: class (HSemiring_ (HIntegral a), HFractional_ a) => HContinuous_ (a :: Hakaru) where type HIntegral (a :: Hakaru) :: Hakaru where {
+ Language.Hakaru.Types.HClasses: class (HSemiring_ a) => HDiscrete_ (a :: Hakaru)
+ Language.Hakaru.Types.HClasses: class HEq_ (a :: Hakaru)
+ Language.Hakaru.Types.HClasses: class (HSemiring_ a) => HFractional_ (a :: Hakaru)
+ Language.Hakaru.Types.HClasses: class HEq_ a => HOrd_ (a :: Hakaru)
+ Language.Hakaru.Types.HClasses: class (HSemiring_ a) => HRadical_ (a :: Hakaru)
+ Language.Hakaru.Types.HClasses: class (HSemiring_ (NonNegative a), HSemiring_ a) => HRing_ (a :: Hakaru) where type NonNegative (a :: Hakaru) :: Hakaru where {
+ Language.Hakaru.Types.HClasses: class HSemiring_ (a :: Hakaru)
+ Language.Hakaru.Types.HClasses: data HContinuous :: Hakaru -> *
+ Language.Hakaru.Types.HClasses: data HDiscrete :: Hakaru -> *
+ Language.Hakaru.Types.HClasses: data HEq :: Hakaru -> *
+ Language.Hakaru.Types.HClasses: data HFractional :: Hakaru -> *
+ Language.Hakaru.Types.HClasses: data HIntegrable :: Hakaru -> *
+ Language.Hakaru.Types.HClasses: data HOrd :: Hakaru -> *
+ Language.Hakaru.Types.HClasses: data HRadical :: Hakaru -> *
+ Language.Hakaru.Types.HClasses: data HRing :: Hakaru -> *
+ Language.Hakaru.Types.HClasses: data HSemiring :: Hakaru -> *
+ Language.Hakaru.Types.HClasses: hContinuous :: HContinuous_ a => HContinuous a
+ Language.Hakaru.Types.HClasses: hContinuous_Sing :: Sing a -> Maybe (HContinuous a)
+ Language.Hakaru.Types.HClasses: hDiscrete :: HDiscrete_ a => HDiscrete a
+ Language.Hakaru.Types.HClasses: hDiscrete_Sing :: Sing a -> Maybe (HDiscrete a)
+ Language.Hakaru.Types.HClasses: hEq :: HEq_ a => HEq a
+ Language.Hakaru.Types.HClasses: hEq_HOrd :: HOrd a -> HEq a
+ Language.Hakaru.Types.HClasses: hEq_Sing :: Sing a -> Maybe (HEq a)
+ Language.Hakaru.Types.HClasses: hFractional :: HFractional_ a => HFractional a
+ Language.Hakaru.Types.HClasses: hFractional_HContinuous :: HContinuous a -> HFractional a
+ Language.Hakaru.Types.HClasses: hFractional_Sing :: Sing a -> Maybe (HFractional a)
+ Language.Hakaru.Types.HClasses: hIntegrable_Sing :: Sing a -> Maybe (HIntegrable a)
+ Language.Hakaru.Types.HClasses: hOrd :: HOrd_ a => HOrd a
+ Language.Hakaru.Types.HClasses: hOrd_Sing :: Sing a -> Maybe (HOrd a)
+ Language.Hakaru.Types.HClasses: hRadical :: HRadical_ a => HRadical a
+ Language.Hakaru.Types.HClasses: hRadical_Sing :: Sing a -> Maybe (HRadical a)
+ Language.Hakaru.Types.HClasses: hRing :: HRing_ a => HRing a
+ Language.Hakaru.Types.HClasses: hRing_Sing :: Sing a -> Maybe (HRing a)
+ Language.Hakaru.Types.HClasses: hSemiring :: HSemiring_ a => HSemiring a
+ Language.Hakaru.Types.HClasses: hSemiring_HFractional :: HFractional a -> HSemiring a
+ Language.Hakaru.Types.HClasses: hSemiring_HIntegralContinuous :: HContinuous a -> HSemiring (HIntegral a)
+ Language.Hakaru.Types.HClasses: hSemiring_HRadical :: HRadical a -> HSemiring a
+ Language.Hakaru.Types.HClasses: hSemiring_HRing :: HRing a -> HSemiring a
+ Language.Hakaru.Types.HClasses: hSemiring_NonNegativeHRing :: HRing a -> HSemiring (NonNegative a)
+ Language.Hakaru.Types.HClasses: hSemiring_Sing :: Sing a -> Maybe (HSemiring a)
+ Language.Hakaru.Types.HClasses: instance (Language.Hakaru.Types.HClasses.HEq_ a, Language.Hakaru.Types.HClasses.HEq_ b) => Language.Hakaru.Types.HClasses.HEq_ (Language.Hakaru.Types.DataKind.HEither a b)
+ Language.Hakaru.Types.HClasses: instance (Language.Hakaru.Types.HClasses.HEq_ a, Language.Hakaru.Types.HClasses.HEq_ b) => Language.Hakaru.Types.HClasses.HEq_ (Language.Hakaru.Types.DataKind.HPair a b)
+ Language.Hakaru.Types.HClasses: instance (Language.Hakaru.Types.HClasses.HOrd_ a, Language.Hakaru.Types.HClasses.HOrd_ b) => Language.Hakaru.Types.HClasses.HOrd_ (Language.Hakaru.Types.DataKind.HEither a b)
+ Language.Hakaru.Types.HClasses: instance (Language.Hakaru.Types.HClasses.HOrd_ a, Language.Hakaru.Types.HClasses.HOrd_ b) => Language.Hakaru.Types.HClasses.HOrd_ (Language.Hakaru.Types.DataKind.HPair a b)
+ Language.Hakaru.Types.HClasses: instance GHC.Classes.Eq (Language.Hakaru.Types.HClasses.HContinuous a)
+ Language.Hakaru.Types.HClasses: instance GHC.Classes.Eq (Language.Hakaru.Types.HClasses.HDiscrete a)
+ Language.Hakaru.Types.HClasses: instance GHC.Classes.Eq (Language.Hakaru.Types.HClasses.HEq a)
+ Language.Hakaru.Types.HClasses: instance GHC.Classes.Eq (Language.Hakaru.Types.HClasses.HFractional a)
+ Language.Hakaru.Types.HClasses: instance GHC.Classes.Eq (Language.Hakaru.Types.HClasses.HIntegrable a)
+ Language.Hakaru.Types.HClasses: instance GHC.Classes.Eq (Language.Hakaru.Types.HClasses.HOrd a)
+ Language.Hakaru.Types.HClasses: instance GHC.Classes.Eq (Language.Hakaru.Types.HClasses.HRadical a)
+ Language.Hakaru.Types.HClasses: instance GHC.Classes.Eq (Language.Hakaru.Types.HClasses.HRing a)
+ Language.Hakaru.Types.HClasses: instance GHC.Classes.Eq (Language.Hakaru.Types.HClasses.HSemiring a)
+ Language.Hakaru.Types.HClasses: instance GHC.Show.Show (Language.Hakaru.Types.HClasses.HContinuous a)
+ Language.Hakaru.Types.HClasses: instance GHC.Show.Show (Language.Hakaru.Types.HClasses.HDiscrete a)
+ Language.Hakaru.Types.HClasses: instance GHC.Show.Show (Language.Hakaru.Types.HClasses.HEq a)
+ Language.Hakaru.Types.HClasses: instance GHC.Show.Show (Language.Hakaru.Types.HClasses.HFractional a)
+ Language.Hakaru.Types.HClasses: instance GHC.Show.Show (Language.Hakaru.Types.HClasses.HIntegrable a)
+ Language.Hakaru.Types.HClasses: instance GHC.Show.Show (Language.Hakaru.Types.HClasses.HOrd a)
+ Language.Hakaru.Types.HClasses: instance GHC.Show.Show (Language.Hakaru.Types.HClasses.HRadical a)
+ Language.Hakaru.Types.HClasses: instance GHC.Show.Show (Language.Hakaru.Types.HClasses.HRing a)
+ Language.Hakaru.Types.HClasses: instance GHC.Show.Show (Language.Hakaru.Types.HClasses.HSemiring a)
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Syntax.IClasses.Eq1 Language.Hakaru.Types.HClasses.HContinuous
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Syntax.IClasses.Eq1 Language.Hakaru.Types.HClasses.HDiscrete
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Syntax.IClasses.Eq1 Language.Hakaru.Types.HClasses.HFractional
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Syntax.IClasses.Eq1 Language.Hakaru.Types.HClasses.HIntegrable
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Syntax.IClasses.Eq1 Language.Hakaru.Types.HClasses.HRadical
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Syntax.IClasses.Eq1 Language.Hakaru.Types.HClasses.HRing
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Syntax.IClasses.Eq1 Language.Hakaru.Types.HClasses.HSemiring
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Syntax.IClasses.JmEq1 Language.Hakaru.Types.HClasses.HContinuous
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Syntax.IClasses.JmEq1 Language.Hakaru.Types.HClasses.HDiscrete
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Syntax.IClasses.JmEq1 Language.Hakaru.Types.HClasses.HFractional
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Syntax.IClasses.JmEq1 Language.Hakaru.Types.HClasses.HIntegrable
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Syntax.IClasses.JmEq1 Language.Hakaru.Types.HClasses.HRadical
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Syntax.IClasses.JmEq1 Language.Hakaru.Types.HClasses.HRing
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Syntax.IClasses.JmEq1 Language.Hakaru.Types.HClasses.HSemiring
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HContinuous_ 'Language.Hakaru.Types.DataKind.HProb
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HContinuous_ 'Language.Hakaru.Types.DataKind.HReal
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HDiscrete_ 'Language.Hakaru.Types.DataKind.HInt
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HDiscrete_ 'Language.Hakaru.Types.DataKind.HNat
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HEq_ 'Language.Hakaru.Types.DataKind.HInt
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HEq_ 'Language.Hakaru.Types.DataKind.HNat
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HEq_ 'Language.Hakaru.Types.DataKind.HProb
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HEq_ 'Language.Hakaru.Types.DataKind.HReal
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HEq_ Language.Hakaru.Types.DataKind.HBool
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HEq_ Language.Hakaru.Types.DataKind.HUnit
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HEq_ a => Language.Hakaru.Types.HClasses.HEq_ ('Language.Hakaru.Types.DataKind.HArray a)
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HFractional_ 'Language.Hakaru.Types.DataKind.HProb
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HFractional_ 'Language.Hakaru.Types.DataKind.HReal
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HOrd_ 'Language.Hakaru.Types.DataKind.HInt
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HOrd_ 'Language.Hakaru.Types.DataKind.HNat
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HOrd_ 'Language.Hakaru.Types.DataKind.HProb
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HOrd_ 'Language.Hakaru.Types.DataKind.HReal
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HOrd_ Language.Hakaru.Types.DataKind.HBool
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HOrd_ Language.Hakaru.Types.DataKind.HUnit
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HOrd_ a => Language.Hakaru.Types.HClasses.HOrd_ ('Language.Hakaru.Types.DataKind.HArray a)
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HRadical_ 'Language.Hakaru.Types.DataKind.HProb
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HRing_ 'Language.Hakaru.Types.DataKind.HInt
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HRing_ 'Language.Hakaru.Types.DataKind.HReal
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HSemiring_ 'Language.Hakaru.Types.DataKind.HInt
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HSemiring_ 'Language.Hakaru.Types.DataKind.HNat
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HSemiring_ 'Language.Hakaru.Types.DataKind.HProb
+ Language.Hakaru.Types.HClasses: instance Language.Hakaru.Types.HClasses.HSemiring_ 'Language.Hakaru.Types.DataKind.HReal
+ Language.Hakaru.Types.HClasses: sing_HContinuous :: HContinuous a -> Sing a
+ Language.Hakaru.Types.HClasses: sing_HDiscrete :: HDiscrete a -> Sing a
+ Language.Hakaru.Types.HClasses: sing_HEq :: HEq a -> Sing a
+ Language.Hakaru.Types.HClasses: sing_HFractional :: HFractional a -> Sing a
+ Language.Hakaru.Types.HClasses: sing_HIntegrable :: HIntegrable a -> Sing a
+ Language.Hakaru.Types.HClasses: sing_HIntegral :: HContinuous a -> Sing (HIntegral a)
+ Language.Hakaru.Types.HClasses: sing_HOrd :: HOrd a -> Sing a
+ Language.Hakaru.Types.HClasses: sing_HRadical :: HRadical a -> Sing a
+ Language.Hakaru.Types.HClasses: sing_HRing :: HRing a -> Sing a
+ Language.Hakaru.Types.HClasses: sing_HSemiring :: HSemiring a -> Sing a
+ Language.Hakaru.Types.HClasses: sing_NonNegative :: HRing a -> Sing (NonNegative a)
+ Language.Hakaru.Types.HClasses: type family HIntegral (a :: Hakaru) :: Hakaru;
+ Language.Hakaru.Types.HClasses: }
+ Language.Hakaru.Types.Sing: class SingI (a :: k)
+ Language.Hakaru.Types.Sing: instance (Language.Hakaru.Types.Sing.SingI a, Language.Hakaru.Types.Sing.SingI b) => Language.Hakaru.Types.Sing.SingI (a 'Language.Hakaru.Types.DataKind.:-> b)
+ Language.Hakaru.Types.Sing: instance (Language.Hakaru.Types.Sing.SingI a, Language.Hakaru.Types.Sing.SingI b) => Language.Hakaru.Types.Sing.SingI (a 'Language.Hakaru.Types.DataKind.:@ b)
+ Language.Hakaru.Types.Sing: instance (Language.Hakaru.Types.Sing.SingI x, Language.Hakaru.Types.Sing.SingI xs) => Language.Hakaru.Types.Sing.SingI (x : xs)
+ Language.Hakaru.Types.Sing: instance (Language.Hakaru.Types.Sing.SingI xs, Language.Hakaru.Types.Sing.SingI xss) => Language.Hakaru.Types.Sing.SingI (xs : xss)
+ Language.Hakaru.Types.Sing: instance (sop ~ Language.Hakaru.Types.DataKind.Code t, Language.Hakaru.Types.Sing.SingI t, Language.Hakaru.Types.Sing.SingI sop) => Language.Hakaru.Types.Sing.SingI ('Language.Hakaru.Types.DataKind.HData t sop)
+ Language.Hakaru.Types.Sing: instance GHC.Classes.Eq (Language.Hakaru.Types.Sing.Sing a)
+ Language.Hakaru.Types.Sing: instance GHC.Classes.Eq (Language.Hakaru.Types.Sing.Sing s)
+ Language.Hakaru.Types.Sing: instance GHC.Show.Show (Language.Hakaru.Types.Sing.Sing a)
+ Language.Hakaru.Types.Sing: instance GHC.Show.Show (Language.Hakaru.Types.Sing.Sing s)
+ Language.Hakaru.Types.Sing: instance GHC.TypeLits.KnownSymbol s => Language.Hakaru.Types.Sing.SingI ('Language.Hakaru.Types.DataKind.TyCon s)
+ Language.Hakaru.Types.Sing: instance GHC.TypeLits.KnownSymbol s => Language.Hakaru.Types.Sing.SingI s
+ Language.Hakaru.Types.Sing: instance Language.Hakaru.Syntax.IClasses.Eq1 Language.Hakaru.Types.Sing.Sing
+ Language.Hakaru.Types.Sing: instance Language.Hakaru.Syntax.IClasses.JmEq1 Language.Hakaru.Types.Sing.Sing
+ Language.Hakaru.Types.Sing: instance Language.Hakaru.Syntax.IClasses.Show1 Language.Hakaru.Types.Sing.Sing
+ Language.Hakaru.Types.Sing: instance Language.Hakaru.Types.Sing.SingI 'Language.Hakaru.Types.DataKind.HInt
+ Language.Hakaru.Types.Sing: instance Language.Hakaru.Types.Sing.SingI 'Language.Hakaru.Types.DataKind.HNat
+ Language.Hakaru.Types.Sing: instance Language.Hakaru.Types.Sing.SingI 'Language.Hakaru.Types.DataKind.HProb
+ Language.Hakaru.Types.Sing: instance Language.Hakaru.Types.Sing.SingI 'Language.Hakaru.Types.DataKind.HReal
+ Language.Hakaru.Types.Sing: instance Language.Hakaru.Types.Sing.SingI 'Language.Hakaru.Types.DataKind.I
+ Language.Hakaru.Types.Sing: instance Language.Hakaru.Types.Sing.SingI '[]
+ Language.Hakaru.Types.Sing: instance Language.Hakaru.Types.Sing.SingI a => Language.Hakaru.Types.Sing.SingI ('Language.Hakaru.Types.DataKind.HArray a)
+ Language.Hakaru.Types.Sing: instance Language.Hakaru.Types.Sing.SingI a => Language.Hakaru.Types.Sing.SingI ('Language.Hakaru.Types.DataKind.HMeasure a)
+ Language.Hakaru.Types.Sing: instance Language.Hakaru.Types.Sing.SingI a => Language.Hakaru.Types.Sing.SingI ('Language.Hakaru.Types.DataKind.K a)
+ Language.Hakaru.Types.Sing: sBool :: Sing HBool
+ Language.Hakaru.Types.Sing: sEither :: Sing a -> Sing b -> Sing (HEither a b)
+ Language.Hakaru.Types.Sing: sList :: Sing a -> Sing (HList a)
+ Language.Hakaru.Types.Sing: sMaybe :: Sing a -> Sing (HMaybe a)
+ Language.Hakaru.Types.Sing: sPair :: Sing a -> Sing b -> Sing (HPair a b)
+ Language.Hakaru.Types.Sing: sSymbol_Bool :: Sing "Bool"
+ Language.Hakaru.Types.Sing: sSymbol_Either :: Sing "Either"
+ Language.Hakaru.Types.Sing: sSymbol_List :: Sing "List"
+ Language.Hakaru.Types.Sing: sSymbol_Maybe :: Sing "Maybe"
+ Language.Hakaru.Types.Sing: sSymbol_Pair :: Sing "Pair"
+ Language.Hakaru.Types.Sing: sSymbol_Unit :: Sing "Unit"
+ Language.Hakaru.Types.Sing: sUnArray :: Sing (HArray a) -> Sing a
+ Language.Hakaru.Types.Sing: sUnEither :: Sing (HEither a b) -> (Sing a, Sing b)
+ Language.Hakaru.Types.Sing: sUnList :: Sing (HList a) -> Sing a
+ Language.Hakaru.Types.Sing: sUnMaybe :: Sing (HMaybe a) -> Sing a
+ Language.Hakaru.Types.Sing: sUnMeasure :: Sing (HMeasure a) -> Sing a
+ Language.Hakaru.Types.Sing: sUnPair :: Sing (HPair a b) -> (Sing a, Sing b)
+ Language.Hakaru.Types.Sing: sUnit :: Sing HUnit
+ Language.Hakaru.Types.Sing: sing :: SingI a => Sing a

Files

− Bench/Bench.hs
@@ -1,20 +0,0 @@-import Criterion.Main--import Control.Monad--import Language.Hakaru.Distribution-import qualified Language.Hakaru.Metropolis as MH-import qualified Language.Hakaru.ImportanceSampler as IS--giveLast :: IO [(a,b)] -> IO (a,b)-giveLast samples = do s <- samples-                      return $ last (take 100 s)--main = defaultMain [-   bcompare [-     bench "is normal 10"  $ whnfIO $ giveLast (IS.sample (replicateM 10 (IS.unconditioned (normal 0 10))) [])-   , bench "is normal 20"  $ whnfIO $ giveLast (IS.sample (replicateM 20 (IS.unconditioned (normal 0 10))) [])-   , bench "mh normal 10"  $ whnfIO $ giveLast (MH.sample (replicateM 10 (MH.unconditioned (normal 0 10))) [])-   , bench "mh normal 20"  $ whnfIO $ giveLast (MH.sample (replicateM 20 (MH.unconditioned (normal 0 10))) [])-   ]- ]
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2014, The Hakaru Team+Copyright (c) 2016, The Hakaru Team  All rights reserved. 
− Language/Hakaru/Arrow.hs
@@ -1,6 +0,0 @@-{-# LANGUAGE TypeOperators #-}-module Language.Hakaru.Arrow where--import Language.Hakaru.Types (Dist)--type a ~~> b = a -> Dist b
− Language/Hakaru/Distribution.hs
@@ -1,232 +0,0 @@-{-# LANGUAGE RankNTypes, BangPatterns, GADTs #-}-{-# OPTIONS -Wall #-}--module Language.Hakaru.Distribution where--import Control.Monad-import Control.Monad.Primitive-import Control.Monad.Loops-import qualified System.Random.MWC as MWC-import Language.Hakaru.Mixture-import Language.Hakaru.Types-import Data.Ix-import Data.Maybe (fromMaybe)-import Data.List (findIndex, foldl')-import Numeric.SpecFunctions-import qualified Data.Map.Strict as M-import qualified Data.Number.LogFloat as LF--mapFst :: (t -> s) -> (t, u) -> (s, u)-mapFst f (a,b) = (f a, b)--dirac :: (Eq a) => a -> Dist a-dirac theta = Dist {logDensity = (\ (Discrete x) -> if x == theta then 0 else log 0),-                    distSample = (\ _ -> return $ Discrete theta)}--bern :: Double -> Dist Bool-bern p = Dist {logDensity = (\ (Discrete x) -> log (if x then p else 1 - p)),-               distSample = (\ g -> do t <- MWC.uniformR (0,1) g-                                       return $ Discrete (t <= p))}--uniform :: Double -> Double -> Dist Double-uniform lo hi =-    let uniformLogDensity lo' hi' x | lo' <= x && x <= hi' = log (recip (hi' - lo'))-        uniformLogDensity _ _ _ = log 0-    in Dist {logDensity = (\ (Lebesgue x) -> uniformLogDensity lo hi x),-             distSample = (\ g -> liftM Lebesgue $ MWC.uniformR (lo, hi) g)}--uniformD :: (Ix a, MWC.Variate a) => a -> a -> Dist a-uniformD lo hi =-    let uniformLogDensity lo' hi' x | lo' <= x && x <= hi' = log density-        uniformLogDensity _ _ _ = log 0-        density = recip (fromInteger (toInteger (rangeSize (lo,hi))))-    in Dist {logDensity = (\ (Discrete x) -> uniformLogDensity lo hi x),-             distSample = (\ g -> liftM Discrete $ MWC.uniformR (lo, hi) g)}--marsaglia :: (MWC.Variate a, Ord a, Floating a, PrimMonad m) => PRNG m -> m (a, a)-marsaglia g = do -- "Marsaglia polar method"-  x <- MWC.uniformR (-1,1) g-  y <- MWC.uniformR (-1,1) g-  let s = x * x + y * y-      q = sqrt ((-2) * log s / s)-  if 1 >= s && s > 0 then return (x * q, y * q) else marsaglia g--choose :: (PrimMonad m) => Mixture k -> PRNG m -> m (k, Prob)-choose (Mixture m) g = do-  let peak = maximum (M.elems m)-      unMix = M.map (LF.fromLogFloat . (/peak)) m-      total = M.foldl' (+) (0::Double) unMix-  p <- MWC.uniformR (0, total) g-  let f !k !v b !p0 = let p1 = p0 + v in if p <= p1 then k else b p1-      err p0 = error ("choose: failure p0=" ++ show p0 ++-                      " total=" ++ show total ++-                      " size=" ++ show (M.size m))-  return $ (M.foldrWithKey f err unMix 0, LF.logFloat total * peak)--chooseIndex :: (PrimMonad m) => [Double] -> PRNG m -> m Int-chooseIndex probs g = do-  p <- MWC.uniform g-  return $ fromMaybe (error ("chooseIndex: failure p=" ++ show p))-           (findIndex (p <=) (scanl1 (+) probs))--normal_rng :: (Real a, Floating a, MWC.Variate a, PrimMonad m) =>-              a -> a -> PRNG m -> m a-normal_rng mu sd g | sd > 0 = do (x, _) <- marsaglia g-                                 return (mu + sd * x)-normal_rng _ _ _ = error "normal: invalid parameters"--normalLogDensity :: Floating a => a -> a -> a -> a-normalLogDensity mu sd x = (-tau * square (x - mu)-                            + log (tau / pi / 2)) / 2-  where square y = y * y-        tau = 1 / square sd--normal :: Double -> Double -> Dist Double -normal mu sd = Dist {logDensity = normalLogDensity mu sd . fromLebesgue,-                     distSample = (\g -> liftM Lebesgue $ normal_rng mu sd g)}--categoricalLogDensity :: (Eq b, Floating a) => [(b, a)] -> b -> a-categoricalLogDensity list x = log $ fromMaybe 0 (lookup x list)--categoricalSample :: (Num b, Ord b, PrimMonad m, MWC.Variate b) =>-    [(t,b)] -> PRNG m -> m t-categoricalSample list g = do-  let total = sum $ map snd list-  p <- MWC.uniformR (0, total) g-  let sumList = scanl1 (\acc (a, b) -> (a, b + snd(acc))) list-      elem' = fst $ head $ filter (\(_,p0) -> p <= p0) sumList-  return elem'--categorical :: Eq a => [(a,Double)] -> Dist a-categorical list = Dist {logDensity = categoricalLogDensity list . fromDiscrete,-                         distSample = (\g -> liftM Discrete $ categoricalSample list g)}--lnFact :: Int -> Double-lnFact = logFactorial---- Makes use of Atkinson's algorithm as described in:--- Monte Carlo Statistical Methods pg. 55------ Further discussion at:--- http://www.johndcook.com/blog/2010/06/14/generating-poisson-random-values/-poisson_rng :: (PrimMonad m) => Double -> PRNG m -> m Int-poisson_rng lambda g' = make_poisson g'-   where smu = sqrt lambda-         b  = 0.931 + 2.53*smu-         a  = -0.059 + 0.02483*b-         vr = 0.9277 - 3.6224/(b - 2)-         arep  = 1.1239 + 1.1368/(b-3.4)-         lnlam = log lambda--         make_poisson :: (PrimMonad m) => PRNG m -> m Int-         make_poisson g = do u <- MWC.uniformR (-0.5,0.5) g-                             v <- MWC.uniformR (0,1) g-                             let us = 0.5 - abs u-                                 k = floor $ (2*a / us + b)*u + lambda + 0.43-                             case () of-                               () | us >= 0.07 && v <= vr -> return k-                               () | k < 0 -> make_poisson g-                               () | us <= 0.013 && v > us -> make_poisson g-                               () | accept_region us v k -> return k-                               _  -> make_poisson g--         accept_region :: Double -> Double -> Int -> Bool-         accept_region us v k = log (v * arep / (a/(us*us)+b)) <=-                                -lambda + (fromIntegral k)*lnlam - lnFact k--poisson :: Double -> Dist Int-poisson l =-    let poissonLogDensity l' x | l' > 0 && x> 0 = (fromIntegral x)*(log l') - lnFact x - l'-        poissonLogDensity l' x | x==0 = -l'-        poissonLogDensity _ _ = log 0-    in Dist {logDensity = poissonLogDensity l . fromDiscrete,-             distSample = (\g -> liftM Discrete $ poisson_rng l g)}---- Direct implementation of  "A Simple Method for Generating Gamma Variables"--- by George Marsaglia and Wai Wan Tsang.-gamma_rng :: (PrimMonad m) => Double -> Double -> PRNG m -> m Double-gamma_rng shape _   _ | shape <= 0.0  = error "gamma: got a negative shape paramater"-gamma_rng _     scl _ | scl <= 0.0  = error "gamma: got a negative scale paramater"-gamma_rng shape scl g | shape <  1.0  = do gvar1 <- gamma_rng (shape + 1) scl g-                                           w <- MWC.uniformR (0,1) g-                                           return $ scl * gvar1 * (w ** recip shape)-gamma_rng shape scl g = do-    let d = shape - 1/3-        c = recip $ sqrt $ 9*d-        -- Algorithm recommends inlining normal generator-        -- n = normal_rng 1 c-    v <- iterateUntil (> 0.0) $ normal_rng 1 c g-        -- (v, g2) = until (\y -> fst y > 0.0) (\ (_, g') -> normal_rng 1 c g') (n g)-    let x = (v - 1) / c-        sqr = x * x-        v3 = v * v * v-    u <- MWC.uniformR (0.0, 1.0) g-    let accept = u < 1.0 - 0.0331*(sqr*sqr) || log u < 0.5*sqr + d*(1.0 - v3 + log v3)-    case accept of-      True -> return $ scl*d*v3-      False -> gamma_rng shape scl g--gammaLogDensity :: Double -> Double -> Double -> Double-gammaLogDensity shape scl x | x>= 0 && shape > 0 && scl > 0 =-     scl * log shape - scl * x + (shape - 1) * log x - logGamma shape-gammaLogDensity _ _ _ = log 0--gamma :: Double -> Double -> Dist Double-gamma shape scl = Dist {logDensity = gammaLogDensity shape scl . fromLebesgue,-                        distSample = (\g -> liftM Lebesgue $ gamma_rng shape scl g)}--beta_rng :: (PrimMonad m) => Double -> Double -> PRNG m -> m Double-beta_rng a b g | a <= 1.0 && b <= 1.0 = do-                 u <- MWC.uniformR (0.0, 1.0) g-                 v <- MWC.uniformR (0.0, 1.0) g-                 let x = u ** (recip a)-                     y = v ** (recip b)-                 case (x+y) <= 1.0 of-                   True -> return $ x / (x + y)-                   False -> beta_rng a b g-beta_rng a b g = do ga <- gamma_rng a 1 g-                    gb <- gamma_rng b 1 g-                    return $ ga / (ga + gb)--betaLogDensity :: Double -> Double -> Double -> Double-betaLogDensity _ _ x | x < 0 || x > 1 = error "beta: value must be between 0 and 1"-betaLogDensity a b _ | a <= 0 || b <= 0 = error "beta: parameters must be positve" -betaLogDensity a b x = (logGamma (a + b)-                        - logGamma a-                        - logGamma b-                        + (a - 1) * log x-                        + (b - 1) * log (1 - x))--beta :: Double -> Double -> Dist Double-beta a b = Dist {logDensity = betaLogDensity a b . fromLebesgue,-                 distSample = (\g -> liftM Lebesgue $ beta_rng a b g)}--laplace_rng :: (PrimMonad m) => Double -> Double -> PRNG m -> m Double-laplace_rng mu sd g = MWC.uniformR (0.0, 1.0) g >>= sample-   where sample u = return $ case u < 0.5 of-                               True  -> mu + sd * log (u + u)-                               False -> mu - sd * log (2.0 - u - u)--laplaceLogDensity :: Floating a => a -> a -> a -> a-laplaceLogDensity mu sd x = - log (2 * sd) - abs (x - mu) / sd--laplace :: Double -> Double -> Dist Double-laplace mu sd = Dist {logDensity = laplaceLogDensity mu sd . fromLebesgue,-                      distSample = (\g -> liftM Lebesgue $ laplace_rng mu sd g)}---- Consider having dirichlet return Vector--- Note: This is actually symmetric dirichlet-dirichlet_rng :: (PrimMonad m) => Int ->  Double -> PRNG m -> m [Double]-dirichlet_rng n' a g' = liftM normalize $ gammas g' n'-  where gammas _ 0 = return ([], 0)-        gammas g n = do (xs, total) <- gammas g (n-1)-                        x <- gamma_rng a 1 g-                        return ((x : xs), x+total)-        normalize (b, total) = map (/ total) b--dirichletLogDensity :: [Double] -> [Double] -> Double-dirichletLogDensity a x | all (> 0) x = sum' (zipWith logTerm a x) + logGamma (sum a)-  where sum' = foldl' (+) 0-        logTerm b y = (b-1) * log y - logGamma b-dirichletLogDensity _ _ = error "dirichlet: all values must be between 0 and 1"-
− Language/Hakaru/ImportanceSampler.hs
@@ -1,94 +0,0 @@-{-# LANGUAGE RankNTypes, NoMonomorphismRestriction, BangPatterns #-}-{-# OPTIONS -W #-}--module Language.Hakaru.ImportanceSampler where---- This is an interpreter that's like Interpreter except conditioning is--- checked at run time rather than by static types.  In other words, we allow--- models to be compiled whose conditioned parts do not match the observation--- inputs.  In exchange, we get to make Measure an instance of Monad, and we--- can express models whose number of observations is unknown at compile time.--import Language.Hakaru.Types-import Language.Hakaru.Mixture (Prob, empty, point, Mixture(..))-import Language.Hakaru.Sampler (Sampler, deterministic, smap, sbind)--import qualified System.Random.MWC as MWC-import Control.Monad.Primitive-import Data.Monoid-import Data.Dynamic-import System.IO.Unsafe-import qualified Data.Map.Strict as M--import qualified Data.Number.LogFloat as LF---- Conditioned sampling-newtype Measure a = Measure { unMeasure :: [Cond] -> Sampler (a, [Cond]) }--bind :: Measure a -> (a -> Measure b) -> Measure b-bind measure continuation =-  Measure (\conds ->-    sbind (unMeasure measure conds)-          (\(a,cds) -> unMeasure (continuation a) cds))--instance Monad Measure where-  return x = Measure (\conds -> deterministic (point (x,conds) 1))-  (>>=)    = bind--updateMixture :: Typeable a => Cond -> Dist a -> Sampler a-updateMixture (Just cond) dist =-    case fromDynamic cond of-      Just y  -> deterministic (point (fromDensity y) density)-          where density = LF.logToLogFloat $ logDensity dist y-      Nothing -> error "did not get data from dynamic source"-updateMixture Nothing     dist = \g -> do e <- distSample dist g-                                          return $ point (fromDensity e) 1-    -conditioned, unconditioned :: Typeable a => Dist a -> Measure a-conditioned   dist = Measure (\(cond:conds) -> smap (\a->(a,conds))-                                               (updateMixture cond    dist))-unconditioned dist = Measure (\      conds  -> smap (\a->(a,conds))-                                               (updateMixture Nothing dist))--factor :: Prob -> Measure ()-factor p = Measure (\conds -> deterministic (point ((), conds) p))--condition :: Eq b => Measure (a, b) -> b -> Measure a-condition m b' =-    Measure (\ conds -> -      sbind (unMeasure m conds)-            (\ ((a,b), cds) ->-                 deterministic (if b==b' then point (a,cds) 1 else empty)))---- Drivers for testing-finish :: Mixture (a, [Cond]) -> Mixture a-finish (Mixture m) = Mixture (M.mapKeysMonotonic (\(a,[]) -> a) m)--empiricalMeasure :: (PrimMonad m, Ord a) => Int -> Measure a -> [Cond] -> m (Mixture a)-empiricalMeasure !n measure conds = do-  gen <- MWC.create-  go n gen empty-    where once = unMeasure measure conds-          go 0 _ m = return m-          go k g m = once g >>= \result -> go (k - 1) g $! mappend m (finish result)--sample :: Measure a -> [Cond] -> IO [(a, Prob)]-sample measure conds = do-  gen <- MWC.create-  unsafeInterleaveIO $ sampleNext gen-      where once = unMeasure measure conds-            mixToTuple = head . M.toList . unMixture-            sampleNext g = do-              u <- once g-              let x = mixToTuple (finish u)-              xs <- unsafeInterleaveIO $ sampleNext g-              return (x : xs)- --  u <- once gen- --  let x = mixToTuple (finish u)- --  xs <- unsafeInterleaveIO $ sample measure conds gen- --  return (x : xs)- -- where once = unMeasure measure conds- --       mixToTuple = head . M.toList . unMixture--logit :: Floating a => a -> a-logit !x = 1 / (1 + exp (- x))
− Language/Hakaru/Lambda.hs
@@ -1,22 +0,0 @@--- The lambda-calculus part of the language, which can be shared-module Language.Hakaru.Lambda(lit, dbl, lam, app, fix, ifThenElse) where--lit :: (Eq a) => a -> a-lit = id---- raw lit is a pain to use.  These are nicer-dbl :: Double -> Double-dbl = lit--lam :: (a -> b) -> (a -> b)-lam f = f--app :: (a -> b) -> a -> b-app f x = f x--fix :: ((a -> b) -> (a -> b)) -> (a -> b)-fix g = f where f = g f--ifThenElse :: Bool -> a -> a -> a-ifThenElse True  t _ = t-ifThenElse False _ f = f
− Language/Hakaru/Metropolis.hs
@@ -1,212 +0,0 @@-{-# LANGUAGE RankNTypes, NoMonomorphismRestriction, BangPatterns,-  DeriveDataTypeable, GADTs, ScopedTypeVariables,-  ExistentialQuantification, StandaloneDeriving #-}-{-# OPTIONS -Wall #-}--module Language.Hakaru.Metropolis where--import qualified System.Random.MWC as MWC-import Control.Monad-import Control.Monad.Primitive-import Data.Dynamic-import Data.Maybe-import Control.Applicative--import qualified Data.Map.Strict as M-import Language.Hakaru.Types--import System.IO.Unsafe--{---Shortcomings of this implementation--* uses parent-conditional sampling for proposal distribution-* re-evaluates entire program at every sample-* lacks way to block sample groups of variables---}--type DistVal = Dynamic- -data XRP where-  XRP :: Typeable e => (Density e, Dist e) -> XRP--unXRP :: Typeable a => XRP -> Maybe (Density a, Dist a)-unXRP (XRP (e,f)) = cast (e,f)--type Visited = Bool-type Observed = Bool-type LL = LogLikelihood---- The first component is the LogLikelihood of the trace--- The second is the LogLikelihood of the newly introduced--- choices. These are used to compute the acceptance ratio-type LL2 = (LL,LL)--type Subloc = Int-type Name = [Subloc]-data DBEntry = DBEntry {-      xrp  :: XRP, -      llhd :: LL, -      vis  :: Visited,-      observed :: Observed }-type Database = M.Map Name DBEntry--data SamplerState where-  S :: { ldb :: Database, -- ldb = local database-         -- (total likelihood, total likelihood of XRPs newly introduced)-         llh2 :: {-# UNPACK #-} !LL2,-         cnds :: [Cond] -- conditions left to process-       } -> SamplerState--type Sampler a = PrimMonad m => SamplerState -> PRNG m -> m (a, SamplerState)--sreturn :: a -> Sampler a-sreturn x s _ = return (x, s)--sbind :: Sampler a -> (a -> Sampler b) -> Sampler b-sbind s k = \ st g -> do (v, s') <- s st g-                         k v s' g--smap :: (a -> b) -> Sampler a -> Sampler b-smap f s = sbind s (\a -> sreturn (f a))--newtype Measure a = Measure {unMeasure :: Name -> Sampler a }-  deriving (Typeable)--return_ :: a -> Measure a-return_ x = Measure $ \ _ -> sreturn x--updateXRP :: Typeable a => Name -> Cond -> Dist a -> Sampler a-updateXRP n obs dist' s@(S {ldb = db}) g = do-    case M.lookup n db of-      Just (DBEntry xd _ _ ob) ->-          do let Just (x, _) = unXRP xd-                 l' = logDensity dist' x-                 d1 = M.insert n (DBEntry (XRP (x,dist')) l' True ob) db-             return (fromDensity x,-                     s {ldb = d1,-                        llh2 = updateLogLikelihood (l',0) (llh2 s)})-      Nothing ->-          do (xnew2, l) <- case obs of-                             Just xdnew ->-                                 do let Just xnew = fromDynamic xdnew-                                    return $ (xnew, logDensity dist' xnew)-                             Nothing ->-                                 do xnew <- distSample dist' g-                                    return (xnew, logDensity dist' xnew)-             let d1 = M.insert n (DBEntry (XRP (xnew2, dist')) l True (isJust obs)) db-             return (fromDensity xnew2,-                     s {ldb = d1,-                        llh2 = updateLogLikelihood (l,l) (llh2 s)})--updateLogLikelihood :: LL2 -> LL2 -> LL2-updateLogLikelihood (llTotal,llFresh) (l,lf) = (llTotal+l, llFresh+lf)--factor :: LL -> Measure ()-factor l = Measure $ \ _ -> \ s _ ->-   do let (llTotal, llFresh) = llh2 s-      return ((), s {llh2 = (llTotal + l, llFresh)})--condition :: Eq b => Measure (a, b) -> b -> Measure a-condition (Measure m) b' = Measure $ \ n ->-    do let comp a b s |  a /= b = s {llh2 = (log 0, 0)}-           comp _ _ s =  s-       sbind (m n) (\ (a, b) s _ -> return (a, comp b b' s))--bind :: Measure a -> (a -> Measure b) -> Measure b-bind (Measure m) cont = Measure $ \ n ->-    sbind (m (0:n)) (\ a -> unMeasure (cont a) (1:n))--conditioned :: Typeable a => Dist a -> Measure a-conditioned dist = Measure $ \ n -> -    \s@(S {cnds = cond:conds }) ->-        updateXRP n cond dist s{cnds = conds}--unconditioned :: Typeable a => Dist a -> Measure a-unconditioned dist = Measure $ \ n ->-    updateXRP n Nothing dist--instance Monad Measure where-  return = return_-  (>>=)  = bind--instance Functor Measure where-  fmap f (Measure x) = Measure $ \n -> smap f (x n)--instance Applicative Measure where-  pure = return_-  (<*>) = app--sapp :: (Sampler (a -> b)) -> Sampler a -> Sampler b-sapp f s = \st g -> do (vf, s')  <- f st g-                       (vs, s'') <- s s' g-                       sreturn (vf vs) s'' g--app :: Measure (a -> b) -> Measure a -> Measure b-app (Measure f) (Measure a) = Measure $ \n -> sapp (f n) (a n)--run :: Measure a -> [Cond] -> IO (a, Database, LL)-run (Measure prog) cds = do-  g <- MWC.create-  (v, S d ll []) <- (prog [0]) (S M.empty (0,0) cds) g-  return (v, d, fst ll)--traceUpdate :: PrimMonad m => Measure a -> Database -> [Cond] -> PRNG m-            -> m (a, Database, LL, LL, LL)-traceUpdate (Measure prog) d cds g = do-  -- let d1 = M.map (\ (x, l, _, ob) -> (x, l, False, ob)) d-  let d1 = M.map (\ s -> s { vis = False }) d-  (v, S d2 (llTotal, llFresh) []) <- (prog [0]) (S d1 (0,0) cds) g-  let (d3, stale_d) = M.partition vis d2-  let llStale = M.foldl' (\ llStale' s -> llStale' + llhd s) 0 stale_d-  return (v, d3, llTotal, llFresh, llStale)--initialStep :: Measure a -> [Cond] ->-               PRNG IO -> IO (a, Database, LL, LL, LL)-initialStep prog cds g = traceUpdate prog M.empty cds g---- TODO: Make a way of passing user-provided proposal distributions-resample :: PrimMonad m => Name -> Database -> Observed -> XRP -> PRNG m ->-            m (Database, LL, LL, LL)-resample name db ob (XRP (x, dist)) g =-    do x' <- distSample dist g-       let fwd = logDensity dist x'-           rvs = logDensity dist x-           l' = fwd-           newEntry = DBEntry (XRP (x', dist)) l' True ob-           db' = M.insert name newEntry db-       return (db', l', fwd, rvs)--transition :: (Typeable a) => Measure a -> [Cond]-           -> a -> Database -> LL -> PRNG IO -> IO [a]-transition prog cds v db ll g =-  do let dbSize = M.size db-         -- choose an unconditioned choice-         (_, uncondDb) = M.partition observed db-     choice <- MWC.uniformR (0, (M.size uncondDb) -1) g-     let (name, (DBEntry xd _ _ ob))  = M.elemAt choice uncondDb-     (db', _, fwd, rvs) <- resample name db ob xd g-     (v', db2, llTotal, llFresh, llStale) <- traceUpdate prog db' cds g-     let a = llTotal - ll-             + rvs - fwd-             + log (fromIntegral dbSize) - log (fromIntegral $ M.size db2)-             + llStale - llFresh-     u <- MWC.uniformR (0 :: Double, 1) g-     if (log u < a) then-         liftM ((:) v') $ unsafeInterleaveIO (transition prog cds v' db2 llTotal g)-     else-         liftM ((:) v) $ unsafeInterleaveIO (transition prog cds v db ll g)--mcmc :: Typeable a => Measure a -> [Cond] -> IO [a]-mcmc prog cds = do-  g <- MWC.create-  (v, d, llTotal, _, _) <- initialStep prog cds g-  transition prog cds v d llTotal g--sample :: Typeable a => Measure a -> [Cond] -> IO [(a, Double)]-sample prog cds  = do -  g <- MWC.create-  (v, d, llTotal, _, _) <- initialStep prog cds g-  (transition prog cds v d llTotal g) >>= return . map (\ x -> (x,1)) 
− Language/Hakaru/Mixture.hs
@@ -1,61 +0,0 @@-{-# LANGUAGE RankNTypes, BangPatterns #-}-{-# OPTIONS -W #-}--module Language.Hakaru.Mixture (Prob, point, empty, scale,-  Mixture(..), toList, mnull, mmap, cross, mode) where--import Data.Monoid-import Data.Ord (comparing)-import Data.List (maximumBy)-import qualified Data.Map.Strict as M-import Data.Number.LogFloat hiding (isInfinite)-import Text.Show (showListWith)-import Numeric (showFFloat)--type Prob = LogFloat---- Mixtures (the results of importance sampling)--newtype Mixture k = Mixture { unMixture :: M.Map k Prob }--instance (Show k) => Show (Mixture k) where-  showsPrec d (Mixture m) = showParen (d > 0) $-    showString "Mixture $ fromList " . showListWith s (M.toList m)-    where s (k,p) = showChar '('-                  . shows k-                  . showChar ','-                  . (if isInfinite l || -42 < l && l < 42-                     then showFFloat Nothing (fromLogFloat p :: Double)-                     else showString "logToLogFloat " . showsPrec 11 l)-                  . showChar ')'-            where l = logFromLogFloat p :: Double--instance (Ord k) => Monoid (Mixture k) where-  mempty        = empty-  mappend m1 m2 = Mixture (M.unionWith (+) (unMixture m1) (unMixture m2))-  mconcat ms    = Mixture (M.unionsWith (+) (map unMixture ms))--empty :: Mixture k-empty = Mixture M.empty--toList :: Mixture k -> [(k, Prob)]-toList = M.toList . unMixture--mnull :: Mixture k -> Bool-mnull = all (0>=) . M.elems . unMixture--point :: k -> Prob -> Mixture k-point k !v = Mixture (M.singleton k v)--scale :: Prob -> Mixture k -> Mixture k-scale !v = Mixture . M.map (v *) . unMixture--mmap :: (Ord k2) => (k1 -> k2) -> Mixture k1 -> Mixture k2-mmap f = Mixture . M.mapKeysWith (+) f . unMixture--cross :: (Ord k) => (k1 -> k2 -> k) -> Mixture k1 -> Mixture k2 -> Mixture k-cross f m1 m2 = mconcat [ mmap (`f` k) (scale v m1)-                        | (k,v) <- M.toList (unMixture m2) ]--mode :: Mixture k -> (k, Prob)-mode (Mixture m) = maximumBy (comparing snd) (M.toList m)
− Language/Hakaru/Sampler.hs
@@ -1,28 +0,0 @@-{-# LANGUAGE RankNTypes #-}-{-# OPTIONS -W #-}--module Language.Hakaru.Sampler (Sampler, deterministic, sbind, smap) where--import Language.Hakaru.Mixture (Mixture, mnull, empty, scale, point)-import Language.Hakaru.Distribution (choose)-import Language.Hakaru.Types-import Control.Monad.Primitive---- Sampling procedures that produce one sample--type Sampler a = PrimMonad m => PRNG m -> m (Mixture a)--deterministic :: Mixture a -> Sampler a-deterministic m _ = return m--sbind :: Sampler a -> (a -> Sampler b) -> Sampler b-sbind s k g = do-  m1 <- s g-  if mnull m1 then -      return empty-  else do (a, v) <- choose m1 g-          m2 <- k a g-          return (scale v m2)--smap :: (a -> b) -> Sampler a -> Sampler b-smap f s = sbind s (\a -> deterministic (point (f a) 1))
− Language/Hakaru/Symbolic.hs
@@ -1,185 +0,0 @@-{-# LANGUAGE GADTs, TypeFamilies, ScopedTypeVariables, FlexibleContexts #-}-{-# OPTIONS -Wall #-}--module Language.Hakaru.Symbolic where--import Prelude hiding (Real)--data Real-data Prob-data Measure a-data Dist a-data Exact--class IntComp repr where-  int                  :: Integer -> repr Integer--class BoolComp repr where-  bool                 :: Bool -> repr Bool--class RealComp repr where-  real                 :: Rational -> repr Real-  exp                  :: repr Real -> repr Real -> repr Real-  sqrt, cos, sin       :: repr Real -> repr Real---- polymorphic operations and integer powering--- probably should restrict 'a' to be some kind of numeric type?-class SymbComp repr where-  add, minus, mul :: repr a -> repr a -> repr a-  pow             :: repr Real -> repr Integer -> repr Real-  scale           :: repr Integer -> repr Real -> repr Real--class MeasMonad repr where-  bind                 :: repr (Measure a) -> (repr a -> repr (Measure b)) -                          -> repr (Measure b)-  ret                  :: repr a -> repr (Measure a)--class Distrib repr where-  uniform, normal :: repr Real -> repr Real -> repr (Dist Real)-  uniformD        :: repr Integer -> repr Integer -> repr (Dist Integer)--class Conditioning repr where-  conditioned, unconditioned :: repr (Dist a) -> repr (Measure a)---- Printer (to Maple)-data Pos = Front | Back-type VarCounter = Int-newtype Maple a = Maple { unMaple :: Pos -> VarCounter -> String }--type family MPL a-type instance MPL Real     = Rational-type instance MPL Integer  = Integer-type instance MPL Bool     = Bool---- if it weren't for the constraints, we could/should use Applicative-pure :: Show (MPL a) => MPL a -> Maple a-pure x = Maple $ \_ _ -> show x--liftA1 :: (String -> String) -> Maple a -> Maple a-liftA1 pr x = Maple $ \f h -> pr (unMaple x f h)--liftA2 :: (String -> String -> String) -> Maple a -> Maple a -> Maple a-liftA2 pr e1 e2 = Maple $ \f h -> pr (unMaple e1 f h) (unMaple e2 f h)---- variant for ret-liftA1M :: (String -> String) -> Maple a -> Maple (Measure a)-liftA1M pr x = Maple $ \f h -> pr (unMaple x f h)---- variant for pow-liftA2aba :: (String -> String -> String) -> Maple a -> Maple b -> Maple a-liftA2aba pr e1 e2 = Maple $ \f h -> pr (unMaple e1 f h) (unMaple e2 f h)---- variant for scale-liftA2baa :: (String -> String -> String) -> Maple b -> Maple a -> Maple a-liftA2baa pr e1 e2 = Maple $ \f h -> pr (unMaple e1 f h) (unMaple e2 f h)--mkPr :: String -> (String -> String)-mkPr s t = s ++ "(" ++ t ++ ")"--d2m :: Maple (Dist a) -> Maple (Measure a)-d2m e = Maple $ unMaple e--infixPr :: String -> (String -> String -> String)-infixPr s a b = a ++ s ++ b---- This is quite scary.  Probably a mistake.-reify :: forall a. Read a => Pos -> VarCounter -> Maple a -> a-reify f h e = (read (unMaple e f h) :: a)--name :: String -> VarCounter -> String-name s h = s ++ show h--var :: String -> VarCounter -> Maple a-var s h = Maple $ \_ _ -> name s h--binder :: (String -> String -> Maybe String) -> -          (String -> String -> VarCounter -> Maybe String) ->-          String -> -          Maple a -> Maple a -> Maple (Dist a)-binder pr1 pr2 oper e1 e2 = Maple $ pr_-  where-    pr_ Front h = let x1 = unMaple e1 Front h-                      x2 = unMaple e2 Front h in-                  case (pr1 x1 x2, pr2 x1 x2 h) of-                    (Just z, Just w)   -> z ++ " * " ++ oper ++ " (" ++ w ++ " * "-                    (Nothing, Just w)  -> oper ++ " (" ++ w ++ " * "-                    (Just z, Nothing)  -> z ++ " * " ++ oper ++ " ("-                    (Nothing, Nothing) -> oper ++ " ("-    pr_ Back h  = ", " ++ (name "x" h) ++ "=" ++ unMaple e1 Back h ++-                  ".." ++ unMaple e2 Back h ++ ")"--instance RealComp Maple where-   -- serious problem here: all exact numbers will be printed as-   -- floats, which will really hamper the use of Maple in any -   -- serious way.  This needs a rethink.-  real  = pure-  exp   = liftA2 $ infixPr "^"-  sqrt  = liftA1 $ mkPr "sqrt"-  cos   = liftA1 $ mkPr "cos"-  sin   = liftA1 $ mkPr "sin"--instance SymbComp Maple where-  add   = liftA2    $ infixPr "+"-  minus = liftA2    $ infixPr "-"-  mul   = liftA2    $ infixPr "*"-  pow   = liftA2aba $ infixPr "^"-  scale = liftA2baa $ infixPr "*"--instance IntComp Maple where-  int  = pure--instance BoolComp Maple where-  bool  = pure--instance MeasMonad Maple where-  ret      = liftA1M $ mkPr "g"-  bind m c = Maple $ \f h -> unMaple m Front h ++ -                             unMaple (c $ var "x" h) f (succ h) ++-                             unMaple m Back h --instance Distrib Maple where-  uniform = binder (\e1 e2 -> Just $ -                     show (1/((read e2 :: Rational) - (read e1 :: Rational)))) -                   (\_ _ _ -> Nothing) "Int"-  uniformD = binder (\e1 e2 -> -                      let d = (read e2 :: Integer) - (read e1) in-                      if d == 1 then Nothing-                      else Just $ "(1 / " ++ show d ++ ")")-                   (\_ _ _ -> Nothing) "Sum"-  normal = binder (\_ _ -> Nothing) -                  (\e1 e2 h -> Just $ "PDF (Normal (" ++ e1 ++ ", " ++ e2 ++ "), " ++ (name "x" h) ++ ")")-                  "Int"--instance Conditioning Maple where-  unconditioned = d2m-  conditioned   = d2m--view :: Maple a -> String-view e = unMaple e Front 0--lift :: Maple Integer -> Maple Real-lift x = Maple $ \f h -> unMaple x f h---- TEST CASES-exp1, exp2, exp3, exp4 :: Maple (Measure Real)-exp1 = unconditioned (uniform (real 1) (real 3)) `bind` ret---- Borel's Paradox Simplified-exp2 = unconditioned (uniformD (int 1) (int 3)) `bind` \s ->-       unconditioned (uniform  (real (-1)) (real 1)) `bind` \x ->-       let y = s `scale` x in ret y---- Borel's Paradox-exp3 = unconditioned (uniformD (int 1) (int 2)) `bind` \s ->-       unconditioned (uniform  (real (-1)) (real 1)) `bind` \x ->-       let y = (Language.Hakaru.Symbolic.sqrt ((real 1 ) `minus` -               (Language.Hakaru.Symbolic.pow (lift s) (int 2)))) `mul`-               (Language.Hakaru.Symbolic.sin x) in ret y  --exp4 = unconditioned (normal (real 1) (real 4)) `bind` ret--test, test2, test3, test4 :: String-test = view exp1-test2 = view exp2-test3 = view exp3-test4 = view exp4
− Language/Hakaru/Types.hs
@@ -1,31 +0,0 @@-{-# LANGUAGE RankNTypes, DeriveDataTypeable, StandaloneDeriving #-}-{-# OPTIONS -W #-}--module Language.Hakaru.Types where--import Data.Dynamic-import Control.Monad.Primitive-import qualified System.Random.MWC as MWC--type PRNG m = MWC.Gen (PrimState m)---- Basic types for conditioning and conditioned sampler-data Density a = Lebesgue !a | Discrete !a deriving Typeable-type Cond = Maybe Dynamic--fromDiscrete :: Density t -> t-fromDiscrete (Discrete a) = a-fromDiscrete _            = error "got a non-discrete sampler"--fromLebesgue :: Density t -> t-fromLebesgue (Lebesgue a) = a-fromLebesgue  _           = error "got a discrete sampler"--fromDensity :: Density t -> t-fromDensity (Discrete a) = a-fromDensity (Lebesgue a) = a--type LogLikelihood = Double-data Dist a = Dist {logDensity :: Density a -> LogLikelihood,-                    distSample :: (PrimMonad m) => PRNG m -> m (Density a)}-deriving instance Typeable1 Dist
− Language/Hakaru/Util/Coda.hs
@@ -1,20 +0,0 @@-module Language.Hakaru.Util.Coda where--import Statistics.Autocorrelation-import qualified Data.Packed.Vector as V-import qualified Data.Vector.Generic as G--effectiveSampleSize :: [Double] -> Double-effectiveSampleSize samples = n / (1 + 2*(G.sum rho))-  where n = fromIntegral (V.dim vec)-        vec = V.fromList samples-        cov = autocovariance vec-        rho = G.map (/ G.head cov) cov--meanVariance :: Fractional a => [a] -> (a,a)-meanVariance lst = (av,sigma2)-  where-    n   = fromIntegral $ length lst-    av  = sum lst / n-    sigma2 = (foldr (\x acc -> sqr (x - av) + acc) 0 lst) / (n - 1)-    sqr x = x * x
− Language/Hakaru/Util/Csv.hs
@@ -1,40 +0,0 @@-{-# LANGUAGE TypeOperators #-}--module Language.Hakaru.Util.Csv ((:::)((:::)), decodeFile, decodeGZipFile,-                 decodeFileStream, decodeGZipFileStream) where--import Data.Csv ( HasHeader(..), FromRecord(..), FromField(..)-                , ToRecord(..), ToField(..), decode)-import qualified Data.Csv.Streaming as CS (decode)-import Codec.Compression.GZip (decompress)-import qualified Data.Foldable as F-import qualified Data.ByteString.Lazy as B-import qualified Data.Vector as V-import Control.Applicative ((<*>), (<$>))--data a ::: b = a ::: b deriving (Eq, Ord, Read, Show)-infixr 5 :::--instance (FromField a, FromRecord b) => FromRecord (a ::: b) where-  parseRecord v | V.null v  = fail "too few fields in input record"-                | otherwise = (:::) <$> parseField (V.head v) <*> parseRecord (V.tail v)--instance (ToField a, ToRecord b) => ToRecord (a ::: b) where-  toRecord (a ::: b) = V.cons (toField a) (toRecord b)--decodeBytes :: FromRecord a => B.ByteString -> [a]-decodeBytes bs = case decode HasHeader bs of-                   Left _ -> []-                   Right v -> V.toList v--decodeFile :: FromRecord a => FilePath -> IO [a]-decodeFile = fmap decodeBytes . B.readFile--decodeGZipFile :: FromRecord a => FilePath -> IO [a]-decodeGZipFile = fmap (decodeBytes . decompress) . B.readFile--decodeFileStream :: FromRecord a => FilePath -> IO [a]-decodeFileStream = fmap (F.toList . CS.decode HasHeader) . B.readFile--decodeGZipFileStream :: FromRecord a => FilePath -> IO [a]-decodeGZipFileStream = fmap (F.toList . CS.decode HasHeader . decompress) . B.readFile
− Language/Hakaru/Util/Extras.hs
@@ -1,79 +0,0 @@-{-|-  Functions on lists and sequences.-  Some of the functions follow the style of Data.Random.Extras -  (from the random-extras package), but are written for use with-  PRNGs from the "mwc-random" package rather than from the "random-fu" package.--}--module Language.Hakaru.Util.Extras where--import qualified Data.Sequence as S-import qualified System.Random.MWC as MWC-import Data.Maybe-import qualified Data.Foldable as F--extract :: S.Seq a -> Int -> Maybe (S.Seq a, a)-extract s i | S.null r = Nothing-            | otherwise  = Just (a S.>< c, b)-    where (a, r) = S.splitAt i s -          (b S.:< c) = S.viewl r--randomExtract :: S.Seq a -> MWC.GenIO -> IO (Maybe (S.Seq a, a))-randomExtract s g = do-  i <- MWC.uniformR (0, S.length s - 1) g-  return $ extract s i--{-| -  Given a sequence, return a *sorted* sequence of-  n randomly selected elements from *distinct positions* in the sequence--}--randomElems :: Ord a => S.Seq a -> Int -> IO (S.Seq a)-randomElems s n = do -  g <- MWC.create-  randomElemsTR S.empty s g n--randomElemsTR :: Ord a => S.Seq a -> S.Seq a -> MWC.GenIO -> Int -> IO (S.Seq a)-randomElemsTR ixs s g n-    | n == S.length s = return $ S.unstableSort s-    | n == 1 = do (_,i) <- fmap fromJust (randomExtract s g)-                  return.S.unstableSort $ i S.<| ixs-    | otherwise = do (s',i) <- fmap fromJust (randomExtract s g)-                     (randomElemsTR $! (i S.<| ixs)) s' g (n-1)--{-|-  Chop a sequence at the given indices. -  Assume number of indices given < length of sequence to be chopped--}--pieces :: S.Seq a -> S.Seq Int -> [S.Seq a]-pieces s ixs = let f (ps,r,x) y = let (p,r') = S.splitAt (y-x) r-                                  in (p:ps,r',y)-                   g (a,b,_) = b:a-               in g $ F.foldl f ([],s,0) ixs--{-|-  Given n, chop a sequence at m random points-  where m = min (length-1, n-1)--}--randomPieces :: Int -> S.Seq a -> IO [S.Seq a]-randomPieces n s-    | n >= l = return $ F.toList $ fmap S.singleton s-    | otherwise = do ixs <- randomElems (S.fromList [1..l-1]) (n-1)-                     return $ pieces s ixs-    where l = S.length s--{-|-  > pairs [1,2,3,4]-  [(1,2),(1,3),(1,4),(2,3),(2,4),(3,4)]-  > pairs [1,2,4,4]-  [(1,2),(1,4),(1,4),(2,4),(2,4),(4,4)]--}--pairs :: [a] -> [(a,a)]-pairs [] = []-pairs (x:xs) = (zip (repeat x) xs) ++ pairs xs--l2Norm :: Floating a => [a] -> a-l2Norm l = sqrt.sum $ zipWith (*) l l
− Language/Hakaru/Util/Visual.hs
@@ -1,43 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}--module Language.Hakaru.Util.Visual where--import System.IO-import Control.Monad--import Data.Aeson-import Data.List-import qualified Data.Text as T-import qualified Data.ByteString.Lazy.Char8 as B---import qualified Data.ByteString.Char8 as BS--plot :: Show a => [a] -> String -> IO ()-plot samples filename = do-  h <- openFile filename WriteMode-  hPrint h samples-  hClose h--batchPrint :: Show a => Int -> [a] -> IO ()-batchPrint n l = do-  let batch = take n l-  print batch-  when (length batch == n) $ batchPrint n (drop n l)--viz :: ToJSON a => Int -> [String] -> [[a]] -> IO ()-viz n name samples = viz' n 50 0 name samples--viz' :: ToJSON a => Int -> Int -> Int -> [String] -> [[a]] -> IO ()-viz' n c cur name samples = do-  putStrLn batch-  when (c+cur < n) $-       viz' n c (cur+c) name (drop c samples)-  where-    total = "total_samples" .= n-    current_sample = "current_sample" .= cur-    chunk = object (zipWith (\ name' s -> T.pack name' .= s)-                            name-                            (transpose $ take c samples))-    batch = B.unpack $ encode-            (object ["rvars" .= chunk,-                     total,-                     current_sample])
− Tests/Distribution.hs
@@ -1,51 +0,0 @@-{-# LANGUAGE BangPatterns #-}--module Tests.Distribution where--import Control.Monad-import qualified System.Random.MWC as MWC--import Language.Hakaru.Types-import Language.Hakaru.Util.Coda-import Language.Hakaru.Distribution hiding (choose)--import Test.QuickCheck-import Test.QuickCheck.Monadic as QM-import Test.Framework.Providers.QuickCheck2 (testProperty)--fromDiscreteToNum = fromIntegral . fromEnum . fromDiscrete-sq x = x * x--almostEqual :: (Num a, Ord a) => a -> a -> a -> Bool-almostEqual tol x y = abs (x - y) < tol--quickArg :: IO ()-quickArg = quickCheckWith stdArgs {maxSuccess = 2000} (\ x -> almostEqual tol x x)-  where tol :: Double-        tol = 1e-5--qtest = [testProperty "checking beta" $ QM.monadicIO betaTest,-         testProperty "checking bern" $ QM.monadicIO bernTest]--betaTest = do-  Positive a <- QM.pick arbitrary-  Positive b <- QM.pick arbitrary-  g <- QM.run $ MWC.create-  samples <- QM.run $ replicateM 1000 $ distSample (beta a b) g-  let (mean, variance) = meanVariance (map fromLebesgue samples)-  QM.assert $ (almostEqual tol mean     (mu  a b)) && -              (almostEqual tol variance (var a b))-  where tol     = 1e-1-        mu a b  = a / (a + b)-        var a b = a*b / ((sq $ a + b) * (a + b + 1))--bernTest = do-   p <- QM.pick $ choose (0, 1)-   g <- QM.run $ MWC.create-   samples <- QM.run $ replicateM 1000 $ distSample (bern p) g-   let (mean, variance) = meanVariance (map fromDiscreteToNum samples)-   QM.assert $ (almostEqual tol mean     (mu  p)) && -               (almostEqual tol variance (var p))-   where tol   = 1e-1-         mu p  = p-         var p = p*(1-p)
− Tests/ImportanceSampler.hs
@@ -1,119 +0,0 @@-{-# LANGUAGE BangPatterns #-}--module Tests.ImportanceSampler where--import Data.Dynamic-import Language.Hakaru.Types-import Language.Hakaru.Lambda-import Language.Hakaru.Distribution-import Language.Hakaru.ImportanceSampler-import qualified System.Random.MWC as MWC---- import Test.QuickCheck.Monadic-import Tests.Models---- Some test programs in our language--test_mixture :: IO ()-test_mixture = MWC.create >>= sample prog_mixture conds >>=-               print . take 10 >>-               putChar '\n' >>-               empiricalMeasure 1000 prog_mixture conds >>=-               print-  where conds = [Just (toDyn (Lebesgue 2 :: Density Double))]--prog_dup :: Measure (Bool, Bool)-prog_dup = do-  let c = unconditioned (bern 0.5)-  x <- c-  y <- c-  return (x,y)--prog_dbn :: Measure Bool-prog_dbn = do-  s0 <- unconditioned (bern 0.75)-  s1 <- unconditioned (if s0 then bern 0.75 else bern 0.25)-  _  <- conditioned   (if s1 then bern 0.90 else bern 0.10)-  s2 <- unconditioned (if s1 then bern 0.75 else bern 0.25)-  _  <- conditioned   (if s2 then bern 0.90 else bern 0.10)-  return s2--test_dbn :: IO ()-test_dbn = MWC.create >>= sample prog_dbn conds >>=-           print . take 10 >>-           putChar '\n' >>-           empiricalMeasure 1000 prog_dbn conds >>=-           print -  where conds = [Just (toDyn (Discrete True)),-                 Just (toDyn (Discrete True))]--prog_hmm :: Integer -> Measure Bool-prog_hmm n = do-  s <- unconditioned (bern 0.75) -  loop_hmm n s--loop_hmm :: Integer -> (Bool -> Measure Bool)-loop_hmm !numLoops s = do-    _ <- conditioned   (if s then bern 0.90 else bern 0.10)-    u <- unconditioned (if s then bern 0.75 else bern 0.25)-    if (numLoops > 1) then loop_hmm (numLoops - 1) u -                      else return s--test_hmm :: IO ()-test_hmm = MWC.create >>= sample (prog_hmm 2) conds >>=-           print . take 10 >>-           putChar '\n' >>-           empiricalMeasure 1000 (prog_hmm 2) conds >>=-           print -  where conds = [Just (toDyn (Discrete True)),-                 Just (toDyn (Discrete True))]--prog_carRoadModel :: Measure (Double, Double)-prog_carRoadModel = do-  speed <- unconditioned (uniform 5 15)-  let z0 = lit 0 -  _ <- conditioned    (normal z0 1)-  z1 <- unconditioned (normal (z0 + speed) 1)-  _ <- conditioned    (normal z1 1)-  z2 <- unconditioned (normal (z1 + speed) 1)	-  _ <- conditioned    (normal z2 1)-  z3 <- unconditioned (normal (z2 + speed) 1)	-  _ <- conditioned    (normal z3 1)-  z4 <- unconditioned (normal (z3 + speed) 1)	-  return (z4, z3)--test_carRoadModel :: IO ()-test_carRoadModel = MWC.create >>= sample prog_carRoadModel conds >>=-                    print . take 10 >>-                    putChar '\n' >>-                    empiricalMeasure 1000 prog_carRoadModel conds >>=-                    print -  where conds = [Just (toDyn (Lebesgue 0  :: Density Double)),-                 Just (toDyn (Lebesgue 11 :: Density Double)), -                 Just (toDyn (Lebesgue 19 :: Density Double)),-                 Just (toDyn (Lebesgue 33 :: Density Double))]--prog_categorical :: Measure Bool-prog_categorical = do -  rain <- unconditioned (categorical [(True, 0.2), (False, 0.8)]) -  sprinkler <- unconditioned (if rain-                              then bern 0.01 else bern 0.4)-  _ <- conditioned (if rain-                    then (if sprinkler then bern 0.99 else bern 0.8)-	            else (if sprinkler then bern 0.90 else bern 0.1))-  return rain--test_categorical :: IO ()-test_categorical = MWC.create >>= sample prog_categorical conds >>=-                   print . take 10 >>-                   putChar '\n' >>-                   empiricalMeasure 1000 prog_categorical conds >>=-                   print -  where conds = [Just (toDyn (Discrete True))]--prog_multiple_conditions :: Measure Double-prog_multiple_conditions = do-  b <- unconditioned (beta 1 1)-  _ <- conditioned (bern b)-  _ <- conditioned (bern b)-  return b
− Tests/Metropolis.hs
@@ -1,45 +0,0 @@-{-# LANGUAGE BangPatterns #-}--module Tests.Metropolis where--import Data.Dynamic--import Language.Hakaru.Types-import Language.Hakaru.Lambda-import Language.Hakaru.Metropolis-import Language.Hakaru.Distribution (bern, normal, uniform, beta)---- import Test.QuickCheck.Monadic--- import Distribution.TestSuite.QuickCheck-import Tests.Models--test_mixture :: IO [Bool]-test_mixture = mcmc prog_mixture [Just (toDyn (Lebesgue (-2) :: Density Double))]--test_multiple_conditions :: IO [Double]-test_multiple_conditions = do-  mcmc prog_multiple_conditions [Just (toDyn (Discrete True)),-                                 Just (toDyn (Discrete False))]--prog_two_normals :: Measure Bool-prog_two_normals = unconditioned (bern 0.5) `bind` \coin ->-       ifThenElse coin (conditioned (normal 0 1))-                       (conditioned (normal 100 1)) `bind` \_ ->-       return coin--test_two_normals :: IO [Bool]-test_two_normals = mcmc prog_two_normals [Just (toDyn (Lebesgue 1 :: Density Double))]--test_normal :: IO [Double]-test_normal = mcmc (unconditioned (normal 1 3)) []--prog_joint =  do-  bias <- unconditioned $ beta 1 1-  coin <- unconditioned $ bern bias-  return (bias, coin)--prog_condition = condition prog_joint True--test_condition :: IO [Double]-test_condition = mcmc prog_condition []-
− Tests/Models.hs
@@ -1,26 +0,0 @@-{-# LANGUAGE NoMonomorphismRestriction, GADTs #-}-module Tests.Models where--import Prelude hiding (Real)--import Language.Hakaru.Syntax2-import Language.Hakaru.Lambda-import qualified Language.Hakaru.Types as T---- if we want to forgo the (D m) constraint, need to decorate the--- program a little more.-prog_mixture :: (Meas m, D m ~ T.Dist ) => m Bool-prog_mixture = do-  c <- unconditioned (bern 0.5)-  _ <- conditioned (ifThenElse c (normal 1 1)-                                 (uniform 0 3))-  return c--prog_multiple_conditions :: (Meas m, D m ~ T.Dist) => m Double-prog_multiple_conditions = do-  b <- unconditioned (beta 1 1)-  _ <- conditioned (bern b)-  _ <- conditioned (bern b)-  return b--
− Tests/Tests.hs
@@ -1,24 +0,0 @@-module Main where--import Prelude hiding (Real)--import qualified Tests.ImportanceSampler as IS-import qualified Tests.Metropolis as MH-import qualified Tests.Distribution as D--import Language.Hakaru.Syntax2-import Language.Hakaru.Lambda-import qualified Language.Hakaru.Types as T--import Test.Framework (defaultMain, testGroup)-import Test.Framework.Providers.HUnit--import Test.HUnit--tests = [-        testGroup "Distribution checks" D.qtest,   -        testCase "alwaysPass" (1 @?= 1)-        --testCase "alwaysFail" (error "Fail!")-    ]--main = defaultMain tests
+ commands/Compile.hs view
@@ -0,0 +1,122 @@+{-# LANGUAGE OverloadedStrings,+             PatternGuards,+             DataKinds,+             KindSignatures,+             GADTs,+             FlexibleContexts,+             TypeOperators+             #-}++module Main where++import qualified Language.Hakaru.Syntax.AST as T+import           Language.Hakaru.Syntax.AST.Transforms+import           Language.Hakaru.Syntax.ABT+import           Language.Hakaru.Syntax.TypeCheck++import           Language.Hakaru.Syntax.IClasses+import           Language.Hakaru.Types.Sing+import           Language.Hakaru.Types.DataKind++import           Language.Hakaru.Pretty.Haskell+import           Language.Hakaru.Command (parseAndInfer)++import           Data.Text+import qualified Data.Text.IO as IO+import           System.IO (stderr)+import           Text.PrettyPrint++import           System.Environment+import           System.FilePath++data Options = Options+  { program  :: String+  , asFunc   :: Maybe String+  }++main :: IO ()+main = do+  args   <- getArgs+  case args of+      [prog1, prog2] -> compileRandomWalk prog1 prog2+      [prog]         -> compileHakaru     prog+      _              -> IO.hPutStrLn stderr+                          "Usage: compile <file>\n\+                          \     | compile <transition_kernel> <initial_measure>"++prettyProg :: (ABT T.Term abt)+           => String+           -> abt '[] a+           -> String+prettyProg name ast =+    renderStyle style+    (cat [ text (name ++ " = ")+         , nest 2 (pretty ast)+         ])++compileHakaru :: String -> IO ()+compileHakaru file = do+    prog <- IO.readFile file+    let target = replaceFileName file (takeBaseName file) ++ ".hs"+    case parseAndInfer prog of+      Left err                 -> IO.hPutStrLn stderr err+      Right (TypedAST typ ast) -> do+        IO.writeFile target . Data.Text.unlines $+          header +++          [ pack $ prettyProg "prog" (et ast) ] +++          footer typ+  where et = expandTransformations++compileRandomWalk :: String -> String -> IO ()+compileRandomWalk f1 f2 = do+    p1 <- IO.readFile f1+    p2 <- IO.readFile f2+    let output = replaceFileName f1 (takeBaseName f1) ++ ".hs"+    case (parseAndInfer p1, parseAndInfer p2) of+      (Right (TypedAST typ1 ast1), Right (TypedAST typ2 ast2)) ->+          -- TODO: Use better error messages for type mismatch+          case (typ1, typ2) of+            (SFun a (SMeasure b), SMeasure c)+              | (Just Refl, Just Refl) <- (jmEq1 a b, jmEq1 b c)+              -> IO.writeFile output . Data.Text.unlines $+                   header +++                   [ pack $ prettyProg "prog1" (expandTransformations ast1) ] +++                   [ pack $ prettyProg "prog2" (expandTransformations ast2) ] +++                   footerWalk+            _ -> IO.hPutStrLn stderr "compile: programs have wrong type"+      (Left err, _) -> IO.hPutStrLn stderr err+      (_, Left err) -> IO.hPutStrLn stderr err++header :: [Text]+header =+  [ "{-# LANGUAGE DataKinds, NegativeLiterals #-}"+  , "module Main where"+  , ""+  , "import           Prelude                          hiding (product)"+  , "import           Language.Hakaru.Runtime.Prelude"+  , "import           Language.Hakaru.Types.Sing"+  , "import qualified System.Random.MWC                as MWC"+  , "import           Control.Monad"+  , ""+  ]++footer :: Sing (a :: Hakaru) -> [Text]+footer typ =+  [ ""+  , "main :: IO ()"+  , "main = do"+  , "  g <- MWC.createSystemRandom"+  , case typ of+      SMeasure _ -> "  forever $ run g prog"+      _          -> "  print prog"+  ]++footerWalk :: [Text]+footerWalk =+  [ ""+  , "main :: IO ()"+  , "main = do"+  , "  g <- MWC.createSystemRandom"+  , "  x <- prog2 g"+  , "  iterateM_ (withPrint $ flip prog1 g) x"+  ]
+ commands/Density.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE OverloadedStrings, DataKinds, GADTs #-}++module Main where++import           Language.Hakaru.Pretty.Concrete+import           Language.Hakaru.Syntax.TypeCheck++import           Language.Hakaru.Types.Sing+import           Language.Hakaru.Disintegrate+import           Language.Hakaru.Evaluation.ConstantPropagation+import           Language.Hakaru.Command++import           Data.Text+import qualified Data.Text.IO as IO+import           System.IO (stderr)++import           System.Environment++main :: IO ()+main = do+  args  <- getArgs+  progs <- mapM readFromFile args+  case progs of+      [prog] -> runDensity prog+      _      -> IO.hPutStrLn stderr "Usage: density <file>"++runDensity :: Text -> IO ()+runDensity prog =+    case parseAndInfer prog of+    Left  err                -> IO.hPutStrLn stderr err+    Right (TypedAST typ ast) ->+        case typ of+            SMeasure _ ->+                case determine (density ast) of+                  Just ast' -> print . pretty $ constantPropagation ast'+                  Nothing   -> IO.hPutStrLn stderr "No density found"+            _               -> IO.hPutStrLn stderr "Density is only available for measure terms"+
+ commands/Disintegrate.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE OverloadedStrings, PatternGuards, DataKinds, GADTs #-}++module Main where++import           Language.Hakaru.Pretty.Concrete+import           Language.Hakaru.Syntax.TypeCheck+import           Language.Hakaru.Syntax.IClasses++import           Language.Hakaru.Types.Sing+import           Language.Hakaru.Disintegrate+import           Language.Hakaru.Evaluation.ConstantPropagation+import           Language.Hakaru.Command++import           Data.Text+import qualified Data.Text.IO as IO+import           System.IO (stderr)++import           System.Environment++main :: IO ()+main = do+  args  <- getArgs+  progs <- mapM readFromFile args+  case progs of+      [prog] -> runDisintegrate prog+      _      -> IO.hPutStrLn stderr "Usage: disintegrate <file>"++runDisintegrate :: Text -> IO ()+runDisintegrate prog =+    case parseAndInfer prog of+    Left  err                -> IO.hPutStrLn stderr err+    Right (TypedAST typ ast) ->+        case typ of+          SMeasure (SData (STyCon sym `STyApp` _ `STyApp` _) _)+            | Just Refl <- jmEq1 sym sSymbol_Pair+            -> case determine (disintegrate ast) of+               Just ast' -> print . pretty $ constantPropagation ast'+               Nothing   -> IO.hPutStrLn stderr "No disintegration found"+          _ -> IO.hPutStrLn stderr "Can only disintegrate a measure over pairs"+
+ commands/HKC.hs view
@@ -0,0 +1,132 @@+{-# LANGUAGE GADTs,+             OverloadedStrings #-}++module Main where++import Language.Hakaru.Evaluation.ConstantPropagation+import Language.Hakaru.Syntax.TypeCheck+import Language.Hakaru.Syntax.AST.Transforms (expandTransformations)+import Language.Hakaru.Command+import Language.Hakaru.CodeGen.Wrapper+import Language.Hakaru.CodeGen.CodeGenMonad+import Language.Hakaru.CodeGen.AST+import Language.Hakaru.CodeGen.Pretty++import           Control.Monad.Reader+import           Data.Text hiding (any,map,filter,foldr)+import qualified Data.Text.IO as IO+import           Text.PrettyPrint (render)+import           Options.Applicative+import           System.IO+import           System.Process+import           System.Exit+import           Prelude hiding (concat)++data Options =+ Options { debug            :: Bool+         , optimize         :: Bool+         , make             :: Maybe String+         , asFunc           :: Maybe String+         , fileIn           :: String+         , fileOut          :: Maybe String+         , par              :: Bool+         , showWeightsOpt   :: Bool+         , showProbInLogOpt :: Bool+         } deriving Show+++main :: IO ()+main = do+  opts <- parseOpts+  prog <- readFromFile (fileIn opts)+  runReaderT (compileHakaru prog) opts++options :: Parser Options+options = Options+  <$> switch (  long "debug"+             <> short 'D'+             <> help "Prints Hakaru src, Hakaru AST, C AST, C src" )+  <*> switch (  long "optimize"+             <> short 'O'+             <> help "Performs constant folding on Hakaru AST" )+  <*> (optional $ strOption (  long "make"+                            <> short 'm'+                            <> help "Compiles generated C code with the compiler ARG"))+  <*> (optional $ strOption (  long "as-function"+                            <> short 'F'+                            <> help "Compiles to a sampling C function with the name ARG" ))+  <*> strArgument (  metavar "INPUT"+                  <> help "Program to be compiled")+  <*> (optional $ strOption (  short 'o'+                            <> metavar "OUTPUT"+                            <> help "output FILE"))+  <*> switch (  short 'j'+             <> help "Generates parallel programs using OpenMP directives")+  <*> switch (  long "show-weights"+             <> short 'w'+             <> help "Shows the weights along with the samples in samplers")+  <*> switch (  long "show-prob-log"+             <> help "Shows prob types as 'exp(<log-domain-value>)' instead of '<value>'")++parseOpts :: IO Options+parseOpts = execParser $ info (helper <*> options)+                       $ fullDesc <> progDesc "Compile Hakaru to C"++compileHakaru :: Text -> ReaderT Options IO ()+compileHakaru prog = ask >>= \config -> lift $ do+  case parseAndInfer prog of+    Left err -> IO.hPutStrLn stderr err+    Right (TypedAST typ ast) -> do+      let ast'    = TypedAST typ $ foldr id ast abtPasses+          outPath = case fileOut config of+                      (Just f) -> f+                      Nothing  -> "-"+          codeGen = wrapProgram ast'+                                (asFunc config)+                                (PrintConfig { showWeights   = showWeightsOpt config+                                             , showProbInLog = showProbInLogOpt config })+          cast    = CAST $ runCodeGenWith codeGen (emptyCG {parallel = par config})+          output  = pack . render . pretty $ cast+      when (debug config) $ do+        putErrorLn $ hrule "Hakaru Type"+        putErrorLn . pack . show $ typ+        when (optimize config) $ do+          putErrorLn $ hrule "Hakaru AST"+          putErrorLn $ pack $ show ast+        putErrorLn $ hrule "Hakaru AST'"+        putErrorLn $ pack $ show ast+        putErrorLn $ hrule "C AST"+        putErrorLn $ pack $ show cast+        putErrorLn $ hrule "Fin"+      case make config of+        Nothing -> writeToFile outPath output+        Just cc -> makeFile cc (fileOut config) (unpack output) config++  where hrule s = concat ["\n<=======================| "+                         ,s," |=======================>\n"]+        abtPasses = [ expandTransformations+                    , constantPropagation ]++putErrorLn :: Text -> IO ()+putErrorLn = IO.hPutStrLn stderr+++makeFile :: String -> Maybe String -> String -> Options -> IO ()+makeFile cc mout prog opts =+  do let p = proc cc $ ["-pedantic"+                       ,"-std=c99"+                       ,"-lm"+                       ,"-xc"+                       ,"-"]+                       ++ (case mout of+                            Nothing -> []+                            Just o  -> ["-o" ++ o])+                       ++ (if par opts then ["-fopenmp"] else [])+     (Just inH, _, _, pH) <- createProcess p { std_in    = CreatePipe+                                             , std_out   = CreatePipe }+     hPutStrLn inH prog+     hClose inH+     exit <- waitForProcess pH+     case exit of+       ExitSuccess -> return ()+       _           -> error $ cc ++ " returned exit code: " ++ show exit
+ commands/Hakaru.hs view
@@ -0,0 +1,93 @@+{-# LANGUAGE OverloadedStrings,+             PatternGuards,+             DataKinds,+             GADTs,+             TypeOperators+             #-}++module Main where++import           Language.Hakaru.Syntax.AST.Transforms+import           Language.Hakaru.Syntax.TypeCheck+import           Language.Hakaru.Syntax.Value++import           Language.Hakaru.Syntax.IClasses+import           Language.Hakaru.Types.Sing+import           Language.Hakaru.Types.DataKind++import           Language.Hakaru.Sample+import           Language.Hakaru.Pretty.Concrete+import           Language.Hakaru.Command (parseAndInfer, readFromFile, Term)++import           Control.Monad++import           Data.Text+import qualified Data.Text.IO as IO+import           System.IO (stderr)+import           Text.PrettyPrint (renderStyle, style, mode, Mode(LeftMode))++import qualified System.Random.MWC as MWC+import           System.Environment++main :: IO ()+main = do+  args   <- getArgs+  g      <- MWC.createSystemRandom+  progs  <- mapM readFromFile args+  case progs of+      [prog1, prog2] -> randomWalk g prog1 prog2+      [prog]         -> runHakaru  g prog+      _              -> IO.hPutStrLn stderr+                          "Usage: hakaru <file>\n\+                          \     | hakaru <transition_kernel> <initial_measure>"++illustrate :: Sing a -> MWC.GenIO -> Value a -> IO ()+illustrate (SMeasure s) g (VMeasure m) = do+    x <- m (VProb 1) g+    case x of+      Just (samp, _) -> illustrate s g samp+      Nothing        -> illustrate (SMeasure s) g (VMeasure m)++illustrate _ _ x = render x++render :: Value a -> IO ()+render = putStrLn . renderStyle style {mode = LeftMode} . prettyValue++runHakaru :: MWC.GenIO -> Text -> IO ()+runHakaru g prog =+    case parseAndInfer prog of+      Left err                 -> IO.hPutStrLn stderr err+      Right (TypedAST typ ast) -> do+        case typ of+          SMeasure _ -> forever (illustrate typ g $ run ast)+          _          -> illustrate typ g $ run ast+    where+    run :: Term a -> Value a+    run = runEvaluate . expandTransformations++randomWalk ::MWC.GenIO -> Text -> Text -> IO ()+randomWalk g p1 p2 =+    case (parseAndInfer p1, parseAndInfer p2) of+      (Right (TypedAST typ1 ast1), Right (TypedAST typ2 ast2)) ->+          -- TODO: Use better error messages for type mismatch+          case (typ1, typ2) of+            (SFun a (SMeasure b), SMeasure c)+              | (Just Refl, Just Refl) <- (jmEq1 a b, jmEq1 b c)+              -> iterateM_ (chain $ run ast1) (run ast2)+            _ -> IO.hPutStrLn stderr "hakaru: programs have wrong type"+      (Left err, _) -> IO.hPutStrLn stderr err+      (_, Left err) -> IO.hPutStrLn stderr err+    where+    run :: Term a -> Value a+    run = runEvaluate . expandTransformations++    chain :: Value (a ':-> b) -> Value ('HMeasure a) -> IO (Value b)+    chain (VLam f) (VMeasure m) = do+      Just (samp,_) <- m (VProb 1) g+      render samp+      return (f samp)++-- From monad-loops+iterateM_ :: Monad m => (a -> m a) -> a -> m b+iterateM_ f = g+    where g x = f x >>= g
+ commands/Mh.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE OverloadedStrings, PatternGuards, DataKinds, GADTs #-}++module Main where++import           Language.Hakaru.Pretty.Concrete  +import           Language.Hakaru.Syntax.TypeCheck++import           Language.Hakaru.Syntax.IClasses+import           Language.Hakaru.Types.Sing+import           Language.Hakaru.Inference+import           Language.Hakaru.Command+  +import           Data.Text+import qualified Data.Text.IO as IO+import           System.IO (stderr)++import           System.Environment++main :: IO ()+main = do+  args  <- getArgs+  progs <- mapM readFromFile args+  case progs of+      [prog2, prog1] -> runMH prog1 prog2+      _              -> IO.hPutStrLn stderr "Usage: mh <target> <proposal>"++runMH :: Text -> Text -> IO ()+runMH prog1 prog2 =+    case (parseAndInfer prog1, parseAndInfer prog2) of+      (Right (TypedAST typ1 ast1), Right (TypedAST typ2 ast2)) ->+          -- TODO: Use better error messages for type mismatch+          case (typ1, typ2) of+            (SFun a (SMeasure b), SMeasure c)+              | (Just Refl, Just Refl) <- (jmEq1 a b, jmEq1 b c)+              -> print . pretty $ mcmc ast1 ast2+            _ -> IO.hPutStrLn stderr "mh: programs have wrong type"+      (Left err, _) -> IO.hPutStrLn stderr err+      (_, Left err) -> IO.hPutStrLn stderr err
+ commands/Momiji.hs view
@@ -0,0 +1,32 @@+{-# LANGUAGE OverloadedStrings, DataKinds, GADTs #-}++module Main where++import qualified Language.Hakaru.Pretty.Maple as Maple+import           Language.Hakaru.Syntax.AST.Transforms+import           Language.Hakaru.Syntax.TypeCheck+import           Language.Hakaru.Command++import           Data.Text+import qualified Data.Text.IO as IO+import           System.IO (stderr)++import           System.Environment++main :: IO ()+main = do+  args <- getArgs+  case args of+      [prog] -> IO.readFile prog >>= runPretty+      []     -> IO.getContents   >>= runPretty+      _      -> IO.hPutStrLn stderr "Usage: momiji <file>"++runPretty :: Text -> IO ()+runPretty prog =+    case parseAndInfer prog of+    Left  err              -> IO.hPutStrLn stderr err+    Right (TypedAST typ ast) -> do+      putStrLn $ Maple.pretty (expandTransformations ast)+      putStrLn $ ","+      putStrLn $ Maple.mapleType typ ""+
+ commands/Normalize.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE OverloadedStrings, DataKinds, GADTs #-}++module Main where++import           Language.Hakaru.Pretty.Concrete  +import           Language.Hakaru.Syntax.AST.Transforms+import           Language.Hakaru.Syntax.TypeCheck+import           Language.Hakaru.Types.Sing++import           Language.Hakaru.Expect (normalize)+import           Language.Hakaru.Evaluation.ConstantPropagation+import           Language.Hakaru.Command++import           Data.Text+import qualified Data.Text.IO as IO+import           System.IO (stderr)++import           System.Environment++main :: IO ()+main = do+  args <- getArgs+  case args of+      [prog] -> IO.readFile prog >>= runNormalize+      []     -> IO.getContents   >>= runNormalize+      _      -> IO.hPutStrLn stderr "Usage: normalize <file>"++runNormalize :: Text -> IO ()+runNormalize prog = either (IO.hPutStrLn stderr) print $ do+  TypedAST typ ast <- parseAndInfer prog+  res <- normalizeUnderLams typ ast+  return (pretty res)++normalizeUnderLams :: Sing a -> Term a -> Either Text (Term a)+normalizeUnderLams (SMeasure _) ast = Right . constantPropagation . normalize $ ast+normalizeUnderLams (SFun _ typ) ast = underLam (normalizeUnderLams typ) ast+normalizeUnderLams _            _   = Left "Can only normalize measures"
+ commands/Pretty.hs view
@@ -0,0 +1,29 @@+{-# LANGUAGE OverloadedStrings, DataKinds, GADTs #-}++module Main where++import           Language.Hakaru.Pretty.Concrete+import           Language.Hakaru.Syntax.AST.Transforms+import           Language.Hakaru.Syntax.TypeCheck+import           Language.Hakaru.Command++import           Data.Text+import qualified Data.Text.IO as IO+import           System.IO (stderr)++import           System.Environment++main :: IO ()+main = do+  args <- getArgs+  case args of+      [prog] -> IO.readFile prog >>= runPretty+      []     -> IO.getContents   >>= runPretty+      _      -> IO.hPutStrLn stderr "Usage: pretty <file>"++runPretty :: Text -> IO ()+runPretty prog =+    case parseAndInfer prog of+    Left  err              -> IO.hPutStrLn stderr err+    Right (TypedAST _ ast) -> print . pretty . expandTransformations $ ast+
+ commands/Simplify.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE CPP, OverloadedStrings, DataKinds, GADTs #-}++module Main where++import           Language.Hakaru.Pretty.Concrete  +import           Language.Hakaru.Syntax.AST.Transforms+import           Language.Hakaru.Syntax.TypeCheck+import           Language.Hakaru.Command (parseAndInfer, readFromFile, Term)++import           Language.Hakaru.Simplify++#if __GLASGOW_HASKELL__ < 710+import           Control.Applicative   (Applicative(..), (<$>))+#endif++import           Data.Text+import qualified Data.Text.IO as IO+import           System.IO (stderr)++import qualified Options.Applicative as O++data Options = Options+  { debug   :: Bool+  , program :: String }++options :: O.Parser Options+options = Options+  <$> O.switch+      ( O.long "debug" O.<>+        O.help "Prints output that is sent to Maple" )+  <*> O.strArgument+      ( O.metavar "PROGRAM" O.<> +        O.help "Program to be simplified" )++parseOpts :: IO Options+parseOpts = O.execParser $ O.info (O.helper <*> options)+      (O.fullDesc O.<> O.progDesc "Simplify a hakaru program")++et :: Term a -> Term a+et = expandTransformations++main :: IO ()+main = do+  args <- parseOpts+  case args of+   Options debug_ file -> do+    prog <- readFromFile file+    runSimplify prog debug_++runSimplify :: Text -> Bool -> IO ()+runSimplify prog debug_ =+    case parseAndInfer prog of+    Left  err              -> IO.hPutStrLn stderr err+    Right (TypedAST _ ast) -> simplifyDebug debug_ (et ast) >>= print . pretty+
hakaru.cabal view
@@ -1,99 +1,281 @@--- Initial hakaru.cabal generated by cabal init.  For further --- documentation, see http://haskell.org/cabal/users-guide/+-- To understand this, see http://haskell.org/cabal/users-guide/ +cabal-version:       >=1.16+build-type:          Simple name:                hakaru-version:             0.1.4-synopsis:            A probabilistic programming embedded DSL   --- description:         +version:             0.3.0+synopsis:            A probabilistic programming language+description:         Hakaru is a simply-typed probabilistic programming language, designed+                     for easy specification of probabilistic models, and inference algorithms. homepage:            http://indiana.edu/~ppaml/ license:             BSD3 license-file:        LICENSE author:              The Hakaru Team maintainer:          ppaml@indiana.edu--- copyright:           +-- copyright: category:            Language-build-type:          Simple--- extra-source-files:  -cabal-version:       >=1.10+-- extra-source-files: -library-  exposed-modules:     Language.Hakaru.Types,-                       Language.Hakaru.Symbolic,-                       Language.Hakaru.Arrow,-                       Language.Hakaru.Mixture,-                       Language.Hakaru.Sampler,-                       Language.Hakaru.ImportanceSampler,-                       Language.Hakaru.Metropolis,-                       Language.Hakaru.Lambda,-                       Language.Hakaru.Distribution,-                       Language.Hakaru.Util.Csv,-                       Language.Hakaru.Util.Extras,-                       Language.Hakaru.Util.Visual,-                       Language.Hakaru.Util.Coda-  other-extensions:    RankNTypes, BangPatterns, GADTs, TypeFamilies, TypeOperators,-                       ConstraintKinds, FlexibleContexts, NoMonomorphismRestriction,-                       DeriveDataTypeable, ScopedTypeVariables, ExistentialQuantification,-                       StandaloneDeriving, OverloadedStrings,-                       FlexibleInstances, RebindableSyntax-  build-depends:       base >=4.6 && <5.0,-                       random >=1.0 && <1.1,-                       transformers >=0.3 && <0.4,-                       containers >=0.5 && <0.6,-                       pretty >=1.1 && <1.2,-                       logfloat >=0.12 && <0.13,-                       hmatrix >=0.16 && <0.17,-                       math-functions >=0.1 && <0.2,-                       vector >=0.10 && <0.11,-                       cassava >=0.4 && <0.5,-                       zlib >=0.5 && <0.6,-                       bytestring >=0.10 && <0.11,-                       aeson >=0.7 && <0.8,-                       text >=1.1 && <1.2,-                       statistics >=0.11 && <0.14,-                       parsec >=3.1 && <3.2,-                       array >=0.4,-                       mwc-random >=0.13 && <0.14,-                       directory >=1.2 && <1.3,-                       integration >= 0.2.0 && < 0.3.0,-                       primitive >= 0.5 && < 0.6,-                       parallel >=3.2 && <3.3,-                       monad-loops >= 0.3.0.2-  -- hs-source-dirs:      -  default-language:    Haskell2010-  ghc-options:         -Wall+----------------------------------------------------------------+Source-Repository head+    Type:     git+    Location: https://github.com/hakaru-dev/hakaru -test-suite hakaru-test-    type:              exitcode-stdio-1.0-    main-is:           Tests/Tests.hs-    other-modules:     Tests.ImportanceSampler,-                       Tests.Models,-                       Tests.Metropolis,-                       Tests.Distribution-    build-depends:     base, Cabal >= 1.10, -                       QuickCheck, -                       HUnit,-                       test-framework,-                       test-framework-quickcheck2,-                       test-framework-hunit,-                       random >=1.0 && <1.1,-                       pretty >=1.1 && <1.2,-                       containers >=0.5 && <0.6,-                       logfloat >=0.12 && <0.13,-                       math-functions >=0.1 && <0.2,-                       statistics >=0.11 && <0.14,-                       hmatrix >=0.16 && <0.17,-                       vector >=0.10 && <0.11,-                       hakaru >= 0.1.3,-                       mwc-random >=0.13 && <0.14,-                       primitive >= 0.5 && < 0.6,-                       monad-loops >= 0.3.0.2-    default-language:  Haskell2010+----------------------------------------------------------------+Flag traceDisintegrate+    Default:     False+    Description: Insert tracing code to help debug disintegration. -benchmark bench-all-    type:              exitcode-stdio-1.0-    hs-source-dirs:    Bench-    main-is:           Bench.hs-    build-depends:     base, deepseq, ghc-prim,-                       criterion, hakaru >= 0.1.3-    ghc-options:       -O2-    default-language:  Haskell2010+----------------------------------------------------------------+Library+    Hs-Source-Dirs:    haskell+    Default-Language:  Haskell2010+    GHC-Options:       -Wall -fwarn-tabs -j6++    if flag(traceDisintegrate)+        Cpp-Options:   -D__TRACE_DISINTEGRATE__++    exposed-modules:   Language.Hakaru.Syntax.IClasses,+                       Language.Hakaru.Syntax.ABT,+                       Language.Hakaru.Syntax.Variable,+                       Language.Hakaru.Syntax.Value,+                       Language.Hakaru.Syntax.Datum,+                       Language.Hakaru.Syntax.DatumABT,+                       Language.Hakaru.Syntax.DatumCase,+                       Language.Hakaru.Types.DataKind,+                       Language.Hakaru.Types.Sing,+                       Language.Hakaru.Types.HClasses,+                       Language.Hakaru.Types.Coercion,+                       Language.Hakaru.Syntax.AST,+                       Language.Hakaru.Syntax.AST.Transforms,+                       Language.Hakaru.Syntax.AST.Sing,+                       Language.Hakaru.Syntax.AST.Eq,+                       Language.Hakaru.Syntax.TypeCheck,+                       Language.Hakaru.Syntax.TypeOf,+                       Language.Hakaru.Syntax.Prelude,+                       Language.Hakaru.Parser.AST,+                       Language.Hakaru.Parser.Maple,+                       Language.Hakaru.Parser.Parser,+                       Language.Hakaru.Parser.SymbolResolve,+                       Language.Hakaru.Pretty.Haskell,+                       Language.Hakaru.Pretty.Concrete,+                       Language.Hakaru.Pretty.Maple,+                       Language.Hakaru.Runtime.Prelude,+                       Language.Hakaru.Observe,+                       Language.Hakaru.Simplify,+                       Language.Hakaru.Sample,+                       Language.Hakaru.Evaluation.Types,+                       Language.Hakaru.Evaluation.Lazy,+                       Language.Hakaru.Evaluation.PEvalMonad,+                       Language.Hakaru.Evaluation.EvalMonad+                       Language.Hakaru.Evaluation.ConstantPropagation,+                       Language.Hakaru.Evaluation.DisintegrationMonad,+                       Language.Hakaru.Evaluation.Coalesce,+                       Language.Hakaru.Disintegrate,+                       Language.Hakaru.Evaluation.ExpectMonad,+                       Language.Hakaru.Expect,+                       Language.Hakaru.Inference,+                       Language.Hakaru.Command,+                       Language.Hakaru.CodeGen.Wrapper,+                       Language.Hakaru.CodeGen.Flatten,+                       Language.Hakaru.CodeGen.CodeGenMonad,+                       Language.Hakaru.CodeGen.Types,+                       Language.Hakaru.CodeGen.AST,+                       Language.Hakaru.CodeGen.Pretty,+                       Data.Number.Nat,+                       Data.Number.Natural++    other-modules:     System.MapleSSH++    build-depends:     base               >= 4.7  && < 5.0,+                       Cabal              >= 1.16,+                       ghc-prim           >= 0.3  && < 0.6,+                       transformers       >= 0.3  && < 0.6,+                       containers         >= 0.5  && < 0.6,+                       semigroups         >= 0.16,+                       pretty             >= 1.1  && < 1.2,+                       logfloat           >= 0.13 && < 0.14,+                       math-functions     >= 0.1  && < 0.3,+                       vector             >= 0.10,+                       indentation-parsec >= 0.0,+                       ansi-terminal      >= 0.6,+                       text               >= 0.11 && < 1.3,+                       parsec             >= 3.1  && < 3.2,+                       mwc-random         >= 0.13 && < 0.14,+                       directory          >= 1.2  && < 1.3,+                       integration        >= 0.2.0 && < 0.3.0,+                       primitive          >= 0.5  && < 0.7,+                       process            >= 1.1  && < 2.0,+                       HUnit              >= 1.2  && < 2.0,+                       mtl                >= 2.1,+                       filepath           >= 1.1.0.2++----------------------------------------------------------------+Test-Suite system-testsuite+    Type:              exitcode-stdio-1.0+    Main-is:           Tests/TestSuite.hs+    Hs-Source-Dirs:    haskell+    Default-Language:  Haskell2010+    GHC-Options:       -Wall -fwarn-tabs++    Build-Depends:     base               >= 4.6  && < 5.0,+                       Cabal              >= 1.16,+                       ghc-prim           >= 0.3  && < 0.6,+                       indentation-parsec >= 0.0,+                       transformers       >= 0.3  && < 0.6,+                       containers         >= 0.5  && < 0.6,+                       semigroups         >= 0.16,+                       logfloat           >= 0.13 && < 0.14,+                       parsec             >= 3.1  && < 3.2,+                       primitive          >= 0.5  && < 0.7,+                       pretty             >= 1.1  && < 1.2,+                       mwc-random         >= 0.13 && < 0.14,+                       math-functions     >= 0.1  && < 0.3,+                       integration        >= 0.2  && < 0.3,+                       ansi-terminal      >= 0.6,+                       HUnit              >= 1.2  && < 2.0,+                       QuickCheck         >= 2.6,+                       process            >= 1.1  && < 2.0,+                       mtl                >= 2.1,+                       vector             >= 0.10,+                       text               >= 0.11 && < 1.3++----------------------------------------------------------------+Executable hakaru+    Main-is:           Hakaru.hs+    Hs-Source-Dirs:    commands+    Default-Language:  Haskell2010+    GHC-Options:       -O2 -Wall -fwarn-tabs++    build-depends:     base             >= 4.7  && < 5.0,+                       mwc-random       >= 0.13 && < 0.14,+                       text             >= 0.11 && < 1.3,+                       pretty           >= 1.1  && < 1.2,+                       hakaru           >= 0.3++----------------------------------------------------------------+Executable compile+    Main-is:           Compile.hs+    Hs-Source-Dirs:    commands+    Default-Language:  Haskell2010+    GHC-Options:       -O2 -Wall -fwarn-tabs++    build-depends:     base             >= 4.7  && < 5.0,+                       mwc-random       >= 0.13 && < 0.14,+                       text             >= 0.11 && < 1.3,+                       pretty           >= 1.1  && < 1.2,+                       filepath         >= 1.3,+                       hakaru           >= 0.3++----------------------------------------------------------------+Executable simplify+    Main-is:           Simplify.hs+    Hs-Source-Dirs:    commands+    Default-Language:  Haskell2010+    GHC-Options:       -O2 -Wall -fwarn-tabs++    build-depends:     base                 >= 4.7  && < 5.0,+                       mwc-random           >= 0.13 && < 0.14,+                       text                 >= 0.11 && < 1.3,+                       pretty               >= 1.1  && < 1.2,+                       optparse-applicative >= 0.11 && < 0.13,+                       hakaru               >= 0.3++----------------------------------------------------------------+Executable density+    Main-is:           Density.hs+    Hs-Source-Dirs:    commands+    Default-Language:  Haskell2010+    GHC-Options:       -O2 -Wall -fwarn-tabs++    build-depends:     base             >= 4.7  && < 5.0,+                       mwc-random       >= 0.13 && < 0.14,+                       text             >= 0.11 && < 1.3,+                       pretty           >= 1.1  && < 1.2,+                       hakaru           >= 0.3+ +----------------------------------------------------------------+Executable disintegrate+    Main-is:           Disintegrate.hs+    Hs-Source-Dirs:    commands+    Default-Language:  Haskell2010+    GHC-Options:       -O2 -Wall -fwarn-tabs++    build-depends:     base             >= 4.7  && < 5.0,+                       mwc-random       >= 0.13 && < 0.14,+                       text             >= 0.11 && < 1.3,+                       pretty           >= 1.1  && < 1.2,+                       hakaru           >= 0.3++----------------------------------------------------------------+Executable pretty+    Main-is:           Pretty.hs+    Hs-Source-Dirs:    commands+    Default-Language:  Haskell2010+    GHC-Options:       -O2 -Wall -fwarn-tabs++    build-depends:     base             >= 4.7  && < 5.0,+                       text             >= 0.11 && < 1.3,+                       pretty           >= 1.1  && < 1.2,+                       hakaru           >= 0.3++----------------------------------------------------------------+Executable momiji+    Main-is:           Momiji.hs+    Hs-Source-Dirs:    commands+    Default-Language:  Haskell2010+    GHC-Options:       -O2 -Wall -fwarn-tabs++    build-depends:     base             >= 4.7  && < 5.0,+                       text             >= 0.11 && < 1.3,+                       hakaru           >= 0.3++----------------------------------------------------------------+Executable normalize+    Main-is:           Normalize.hs+    Hs-Source-Dirs:    commands+    Default-Language:  Haskell2010+    GHC-Options:       -O2 -Wall -fwarn-tabs++    build-depends:     base             >= 4.7  && < 5.0,+                       mwc-random       >= 0.13 && < 0.14,+                       text             >= 0.11 && < 1.3,+                       mtl              >= 2.1,+                       pretty           >= 1.1  && < 1.2,+                       hakaru           >= 0.3+++----------------------------------------------------------------+Executable hkc+    Main-is:           HKC.hs+    Hs-Source-Dirs:    commands+    Default-Language:  Haskell2010+    GHC-Options:       -O2 -Wall -fwarn-tabs++    build-depends:     base                 >= 4.7  && < 5.0,+                       containers           >= 0.5  && < 0.6,+                       text                 >= 0.11 && < 1.3,+                       mtl                  >= 2.1,+                       optparse-applicative >= 0.11 && < 0.13,+                       pretty               >= 1.1  && < 1.2,+                       process              >= 1.1  && < 2.0,+                       hakaru               >= 0.3,+                       semigroups           >= 0.16+++----------------------------------------------------------------+Executable mh+    Main-is:           Mh.hs+    Hs-Source-Dirs:    commands+    Default-Language:  Haskell2010+    GHC-Options:       -O2 -Wall -fwarn-tabs++    build-depends:     base             >= 4.7  && < 5.0,+                       mwc-random       >= 0.13 && < 0.14,+                       text             >= 0.11 && < 1.3,+                       mtl              >= 2.1,+                       pretty           >= 1.1  && < 1.2,+                       hakaru           >= 0.3++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Data/Number/Nat.hs view
@@ -0,0 +1,165 @@+-- TODO: merge with the Posta version. And release them as a standalone package+{-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2015.12.17+-- |+-- Module      :  Data.Number.Nat+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  Haskell98 + CPP+--+-- A data type for natural numbers (aka non-negative integers).+----------------------------------------------------------------+module Data.Number.Nat+    ( Nat()+    , fromNat+    , toNat+    , unsafeNat+    , MaxNat(..)+    ) where++#if __GLASGOW_HASKELL__ < 710+import Data.Monoid (Monoid(..))+#endif++----------------------------------------------------------------+----------------------------------------------------------------+-- | Natural numbers, with fixed-width à la 'Int'. N.B., the 'Num'+-- instance will throw errors on subtraction, negation, and+-- 'fromInteger' when the result is not a natural number.+newtype Nat = Nat Int+    deriving (Eq, Ord, Show)++-- TODO: should we define our own Show instance, in order to just+-- show the Int itself, relying on our 'fromInteger' definition to+-- preserve cut&paste-ability? If so, then we should ensure that+-- the Read instance is optional in whether the \"Nat\" is there+-- or not.++-- N.B., we cannot derive Read, since that would inject invalid numbers!+instance Read Nat where+    readsPrec d =+        readParen (d > 10) $ \s0 -> do+            ("Nat", s1) <- lex s0+            (i,     s2) <- readsPrec 11 s1+            maybe [] (\n -> [(n,s2)]) (toNat i)+++-- | Safely convert a natural number to an integer.+fromNat :: Nat -> Int+fromNat (Nat i) = i+{-# INLINE fromNat #-}+++-- | Safely convert an integer to a natural number. Returns @Nothing@+-- if the integer is negative.+toNat :: Int -> Maybe Nat+toNat x+    | x < 0     = Nothing+    | otherwise = Just (Nat x)+{-# INLINE toNat #-}+++-- | Unsafely convert an integer to a natural number. Throws an+-- error if the integer is negative.+unsafeNat :: Int -> Nat+unsafeNat x+    | x < 0     = error _errmsg_unsafeNat+    | otherwise = Nat x+{-# INLINE unsafeNat #-}+++instance Num Nat where+    Nat i + Nat j   = Nat (i + j)+    Nat i * Nat j   = Nat (i * j)+    Nat i - Nat j+        | i >= j    = Nat (i - j)+        | otherwise = error _errmsg_subtraction+    negate _        = error _errmsg_negate+    abs n           = n+    signum _        = Nat 1+    fromInteger i+        | i >= 0 && n >= 0 = Nat n+        | otherwise = error _errmsg_fromInteger+        where+        n :: Int+        n = fromInteger i+    {-# INLINE (+) #-}+    {-# INLINE (*) #-}+    {-# INLINE (-) #-}+    {-# INLINE negate #-}+    {-# INLINE abs #-}+    {-# INLINE signum #-}+    {-# INLINE fromInteger #-}++instance Enum Nat where+    succ (Nat i) = if i /= maxBound then Nat (i+1) else error _errmsg_succ+    pred (Nat i) = if i /= 0        then Nat (i-1) else error _errmsg_pred+    toEnum n     = if n >= 0        then Nat n     else error _errmsg_toEnum+    fromEnum (Nat i) = i++    enumFrom       (Nat i)                 = map Nat (enumFrom       i)+    enumFromThen   (Nat i) (Nat j)         = map Nat (enumFromThen   i j)+    enumFromTo     (Nat i)         (Nat k) = map Nat (enumFromTo     i   k)+    enumFromThenTo (Nat i) (Nat j) (Nat k) = map Nat (enumFromThenTo i j k)+    {-# INLINE succ #-}+    {-# INLINE pred #-}+    {-# INLINE toEnum #-}+    {-# INLINE fromEnum #-}+    {-# INLINE enumFrom #-}+    {-# INLINE enumFromThen #-}+    {-# INLINE enumFromTo #-}+    {-# INLINE enumFromThenTo #-}++instance Real Nat where+    toRational (Nat i) = toRational i+    {-# INLINE toRational #-}++instance Integral Nat where+    quot    (Nat i) (Nat j) = Nat (quot i j)+    rem     (Nat i) (Nat j) = Nat (rem  i j)+    quotRem (Nat i) (Nat j) = case quotRem i j of (q,r) -> (Nat q, Nat r)+    div    = quot+    mod    = rem+    divMod = quotRem+    toInteger (Nat i) = toInteger i+    {-# INLINE quot #-}+    {-# INLINE rem #-}+    {-# INLINE div #-}+    {-# INLINE mod #-}+    {-# INLINE quotRem #-}+    {-# INLINE divMod #-}+    {-# INLINE toInteger #-}+++----------------------------------------------------------------+newtype MaxNat = MaxNat { unMaxNat :: Nat }++instance Monoid MaxNat where+    mempty                        = MaxNat 0+    mappend (MaxNat m) (MaxNat n) = MaxNat (max m n)+++----------------------------------------------------------------+_errmsg_unsafeNat, _errmsg_subtraction, _errmsg_negate, _errmsg_fromInteger, _errmsg_succ, _errmsg_pred, _errmsg_toEnum+    :: String+_errmsg_unsafeNat   = "unsafeNat: negative input"+_errmsg_subtraction = "(-)@Nat: Num is a bad abstraction"+_errmsg_negate      = "negate@Nat: Num is a bad abstraction"+_errmsg_fromInteger = "fromInteger@Nat: Num is a bad abstraction"+_errmsg_succ        = "succ@Nat: No successor of the maxBound"+_errmsg_pred        = "pred@Nat: No predecessor of zero"+_errmsg_toEnum      = "toEnum@Nat: negative input"+{-# NOINLINE _errmsg_unsafeNat #-}+{-# NOINLINE _errmsg_subtraction #-}+{-# NOINLINE _errmsg_negate #-}+{-# NOINLINE _errmsg_fromInteger #-}+{-# NOINLINE _errmsg_succ #-}+{-# NOINLINE _errmsg_pred #-}+{-# NOINLINE _errmsg_toEnum #-}++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Data/Number/Natural.hs view
@@ -0,0 +1,210 @@+-- TODO: merge with the Posta version. And release them as a standalone package+{-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2015.12.17+-- |+-- Module      :  Data.Number.Natural+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  Haskell98 + CPP+--+-- A data type for natural numbers (aka non-negative integers).+----------------------------------------------------------------+module Data.Number.Natural+    ( Natural()+    , fromNatural+    , toNatural+    , unsafeNatural+    , MaxNatural(..)+    , NonNegativeRational+    , fromNonNegativeRational+    , toNonNegativeRational+    , unsafeNonNegativeRational+    ) where++#if __GLASGOW_HASKELL__ < 710+import Data.Monoid (Monoid(..))+#endif+import Data.Ratio++----------------------------------------------------------------+----------------------------------------------------------------+-- | Natural numbers, with unbounded-width à la 'Integer'. N.B.,+-- the 'Num' instance will throw errors on subtraction, negation,+-- and 'fromInteger' when the result is not a natural number.+newtype Natural = Natural Integer+    deriving (Eq, Ord)++instance Show Natural where+    show (Natural i) = show i++-- TODO: should we define our own Show instance, in order to just+-- show the Integer itself, relying on our 'fromInteger' definition+-- to preserve cut&paste-ability? If so, then we should ensure that+-- the Read instance is optional in whether the \"Natural\" is there+-- or not.++-- N.B., we cannot derive Read, since that would inject invalid numbers!+instance Read Natural where+    readsPrec d =+        readParen (d > 10) $ \s0 -> do+            ("Natural", s1) <- lex s0+            (i,         s2) <- readsPrec 11 s1+            maybe [] (\n -> [(n,s2)]) (toNatural i)+++-- | Safely convert a natural number to an integer.+fromNatural :: Natural -> Integer+fromNatural (Natural i) = i+{-# INLINE fromNatural #-}+++-- | Safely convert an integer to a natural number. Returns @Nothing@+-- if the integer is negative.+toNatural :: Integer -> Maybe Natural+toNatural x+    | x < 0     = Nothing+    | otherwise = Just (Natural x)+{-# INLINE toNatural #-}+++-- | Unsafely convert an integer to a natural number. Throws an+-- error if the integer is negative.+unsafeNatural :: Integer -> Natural+unsafeNatural x+    | x < 0     = error _errmsg_unsafeNatural+    | otherwise = Natural x+{-# INLINE unsafeNatural #-}+++instance Num Natural where+    Natural i + Natural j   = Natural (i + j)+    Natural i * Natural j   = Natural (i * j)+    Natural i - Natural j+        | i >= j    = Natural (i - j)+        | otherwise = error _errmsg_subtraction+    negate _        = error _errmsg_negate+    abs n           = n+    signum _        = Natural 1+    fromInteger i+        | i >= 0 && i >= 0 = Natural i+        | otherwise = error _errmsg_fromInteger+    {-# INLINE (+) #-}+    {-# INLINE (*) #-}+    {-# INLINE (-) #-}+    {-# INLINE negate #-}+    {-# INLINE abs #-}+    {-# INLINE signum #-}+    {-# INLINE fromInteger #-}++instance Enum Natural where+    succ (Natural i) = Natural (i+1)+    pred (Natural i)+        | i /= 0     = Natural (i-1)+        | otherwise  = error _errmsg_pred+    toEnum n+        | n >= 0     = Natural (toInteger n)+        | otherwise  = error _errmsg_toEnum+    fromEnum (Natural i) = fromEnum i++    enumFrom       (Natural i)             = map Natural (enumFrom i)+    enumFromThen   (Natural i) (Natural j) = map Natural (enumFromThen i j)+    enumFromTo     (Natural i) (Natural k) = map Natural (enumFromTo i k)+    enumFromThenTo (Natural i) (Natural j) (Natural k) =+        map Natural (enumFromThenTo i j k)+    {-# INLINE succ #-}+    {-# INLINE pred #-}+    {-# INLINE toEnum #-}+    {-# INLINE fromEnum #-}+    {-# INLINE enumFrom #-}+    {-# INLINE enumFromThen #-}+    {-# INLINE enumFromTo #-}+    {-# INLINE enumFromThenTo #-}++instance Real Natural where+    toRational (Natural i) = toRational i+    {-# INLINE toRational #-}++instance Integral Natural where+    quot    (Natural i) (Natural j) = Natural (quot i j)+    rem     (Natural i) (Natural j) = Natural (rem  i j)+    quotRem (Natural i) (Natural j) =+        case quotRem i j of+        (q,r) -> (Natural q, Natural r)+    div    = quot+    mod    = rem+    divMod = quotRem+    toInteger (Natural i) = i+    {-# INLINE quot #-}+    {-# INLINE rem #-}+    {-# INLINE div #-}+    {-# INLINE mod #-}+    {-# INLINE quotRem #-}+    {-# INLINE divMod #-}+    {-# INLINE toInteger #-}+++----------------------------------------------------------------+newtype MaxNatural = MaxNatural { unMaxNatural :: Natural }++instance Monoid MaxNatural where+    mempty                                = MaxNatural 0+    mappend (MaxNatural m) (MaxNatural n) = MaxNatural (max m n)+++----------------------------------------------------------------+-- TODO: come up with a more succinct name...+type NonNegativeRational = Ratio Natural++-- | Safely convert a non-negative rational to a rational.+fromNonNegativeRational :: NonNegativeRational -> Rational+fromNonNegativeRational x =+    fromNatural (numerator x) % fromNatural (denominator x)+    -- TODO: can we use @(:%)@ directly?+{-# INLINE fromNonNegativeRational #-}+++-- | Safely convert a rational to a non-negative rational. Returns+-- @Nothing@ if the argument is negative.+toNonNegativeRational :: Rational -> Maybe NonNegativeRational+toNonNegativeRational x = do+    n <- toNatural (numerator x)+    d <- toNatural (denominator x)+    return (n % d)+    -- TODO: can we use @(:%)@ directly?+{-# INLINE toNonNegativeRational #-}+++-- | Unsafely convert a rational to a non-negative rational. Throws+-- an error if the argument is negative.+unsafeNonNegativeRational :: Rational -> NonNegativeRational+unsafeNonNegativeRational x =+    case toNonNegativeRational x of+    Just y  -> y+    Nothing -> error _errmsg_unsafeNonNegativeRational+{-# INLINE unsafeNonNegativeRational #-}+++----------------------------------------------------------------+_errmsg_unsafeNatural, _errmsg_subtraction, _errmsg_negate, _errmsg_fromInteger, _errmsg_pred, _errmsg_toEnum, _errmsg_unsafeNonNegativeRational+    :: String+_errmsg_unsafeNatural = "unsafeNatural: negative input"+_errmsg_subtraction   = "(-)@Natural: Num is a bad abstraction"+_errmsg_negate        = "negate@Natural: Num is a bad abstraction"+_errmsg_fromInteger   = "fromInteger@Natural: Num is a bad abstraction"+_errmsg_pred          = "pred@Natural: No predecessor of zero"+_errmsg_toEnum        = "toEnum@Natural: negative input"+_errmsg_unsafeNonNegativeRational = "unsafeNonNegativeRational: negative input"+{-# NOINLINE _errmsg_unsafeNatural #-}+{-# NOINLINE _errmsg_subtraction #-}+{-# NOINLINE _errmsg_negate #-}+{-# NOINLINE _errmsg_fromInteger #-}+{-# NOINLINE _errmsg_pred #-}+{-# NOINLINE _errmsg_toEnum #-}+{-# NOINLINE _errmsg_unsafeNonNegativeRational #-}++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/CodeGen/AST.hs view
@@ -0,0 +1,388 @@+--------------------------------------------------------------------------------+--                                                                 2016.09.08+-- |+-- Module      :  Language.Hakaru.CodeGen.AST+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  zsulliva@indiana.edu+-- Stability   :  experimental+-- Portability :  GHC-only+--+--   An AST for the C Family and preprocessor+-- Much of this is based on Manuel M T Chakravarty and Benedikt+-- Hubar's "language-c" package+--+--------------------------------------------------------------------------------++module Language.Hakaru.CodeGen.AST+  ( Preprocessor(..), Ident(..), CAST(..), CExtDecl(..), CFunDef(..)++  -- declaration constructors+  , CDecl(..), CDeclr(..), CDeclSpec(..), CStorageSpec(..), CTypeQual(..)+  , CDirectDeclr(..), CTypeSpec(..), CSUSpec(..), CSUTag(..), CEnum(..)+  , CInit(..), CPartDesig(..), CFunSpec(..), CPtrDeclr(..)++  -- statements and expression constructors+  , CStat(..), CCompoundBlockItem(..), CExpr(..), CConst(..), CUnaryOp(..)+  , CBinaryOp(..), CAssignOp(..)++  -- infix and smart constructors+  , (.>.),(.<.),(.==.),(.||.),(.&&.),(.*.),(./.),(.-.),(.+.),(.=.),(.+=.),(.*=.)+  , (.>=.),(.<=.)+  , seqCStat+  , indirect, address, intE, floatE, stringE, mkUnary+  , exp, expm1, log, log1p, sqrt, rand, infinityE, negInfinityE, printfE+  ) where++import Prelude hiding (exp,log,sqrt)+++--------------------------------------------------------------------------------+--                               Top Level                                    --+--------------------------------------------------------------------------------++data CAST+  = CAST [CExtDecl]+  deriving (Show, Eq, Ord)+++data CExtDecl+  = CDeclExt    CDecl+  | CFunDefExt  CFunDef+  | CCommentExt String+  | CPPExt      Preprocessor+  deriving (Show, Eq, Ord)++data CFunDef+  = CFunDef [CDeclSpec] CDeclr [CDecl] CStat+  deriving (Show, Eq, Ord)++{-+  This is currently a very rough AST for preprocessor. Preprocessor macros+  can be inserted at the top level and at the statement level+-}+data Preprocessor+  = PPDefine  String String+  | PPInclude String+  | PPUndef   String+  | PPIf      String+  | PPIfDef   String+  | PPIfNDef  String+  | PPElse    String+  | PPElif    String+  | PPEndif   String+  | PPError   String+  | PPPragma  [String]+  deriving (Show, Eq, Ord)++data Ident+ = Ident String+ deriving (Show, Eq, Ord)+++--------------------------------------------------------------------------------+--                               C Declarations                               --+--------------------------------------------------------------------------------+{-+  C Declarations provide tools for laying out memory objections.+-}++data CDecl+  = CDecl [CDeclSpec] [(CDeclr, Maybe CInit)]+  deriving (Show, Eq, Ord)++----------------+-- Specifiers --+----------------++-- top level specifier+data CDeclSpec+  = CStorageSpec CStorageSpec+  | CTypeSpec    CTypeSpec+  | CTypeQual    CTypeQual+  | CFunSpec     CFunSpec+  deriving (Show, Eq, Ord)++data CStorageSpec+  = CTypeDef+  | CExtern+  | CStatic+  | CAuto+  | CRegister+  deriving (Show, Eq, Ord)++data CTypeQual+  = CConstQual+  | CVolatQual+  deriving (Show, Eq, Ord)++data CFunSpec = Inline+  deriving (Show, Eq, Ord)++data CTypeSpec+  = CVoid+  | CChar+  | CShort+  | CInt+  | CLong+  | CFloat+  | CDouble+  | CSigned+  | CUnsigned+  | CSUType      CSUSpec+  | CTypeDefType Ident+  | CEnumType    CEnum+  deriving (Show, Eq, Ord)++data CSUSpec+  = CSUSpec CSUTag (Maybe Ident) [CDecl]+  deriving (Show, Eq, Ord)++data CSUTag+  = CStructTag+  | CUnionTag+  deriving (Show, Eq, Ord)++data CEnum+  = CEnum (Maybe Ident) [(Ident, Maybe CExpr)]+  deriving (Show, Eq, Ord)++-----------------+-- Declarators --+-----------------+{-+  Declarators give us labels to point at and describe the level of indirection.+  between a label and the underlieing memory+-}++data CDeclr+  = CDeclr (Maybe CPtrDeclr) [CDirectDeclr]+  deriving (Show, Eq, Ord)++data CPtrDeclr = CPtrDeclr [CTypeQual]+  deriving (Show, Eq, Ord)++-- this is incomplete+data CDirectDeclr+  = CDDeclrIdent Ident+  | CDDeclrArr   CDirectDeclr CExpr+  | CDDeclrFun   CDirectDeclr [CTypeSpec]+  deriving (Show, Eq, Ord)++------------------+-- Initializers --+------------------+{-+  Initializers allow us to fill our objects with values right as they are+  declared rather than as a side-effect later in the program.+-}++data CInit+  = CInitExpr CExpr+  | CInitList [([CPartDesig], CInit)]+  deriving (Show, Eq, Ord)++data CPartDesig+  = CArrDesig    CExpr+  | CMemberDesig CExpr+  deriving (Show, Eq, Ord)++--------------------------------------------------------------------------------+--                                C Statments                                 --+--------------------------------------------------------------------------------+{-+  The separation between C Statements and C Expressions is fuzzy. Here we take+  statements as side-effecting operations sequenced by the ";" in pedantic C+  concrete syntax. Though operators like "++" that are represented as C+  Expressions in this AST also perform side-effects.+-}++data CStat+  = CLabel    Ident CStat+  | CGoto     Ident+  | CSwitch   CExpr CStat+  | CCase     CExpr CStat+  | CDefault  CStat+  | CExpr     (Maybe CExpr)+  | CCompound [CCompoundBlockItem]+  | CIf       CExpr CStat (Maybe CStat)+  | CWhile    CExpr CStat Bool+  | CFor      (Maybe CExpr) (Maybe CExpr) (Maybe CExpr) CStat+  | CCont+  | CBreak+  | CReturn   (Maybe CExpr)+  | CComment  String+  | CPPStat   Preprocessor+  deriving (Show, Eq, Ord)++data CCompoundBlockItem+  = CBlockStat CStat+  | CBlockDecl CDecl+  deriving (Show, Eq, Ord)++--------------------------------------------------------------------------------+--                                C Expressions                               --+--------------------------------------------------------------------------------+{-+  See C Statments...+-}++data CExpr+  = CComma       [CExpr]+  | CAssign      CAssignOp CExpr CExpr+  | CCond        CExpr CExpr CExpr+  | CBinary      CBinaryOp CExpr CExpr+  | CCast        CDecl CExpr+  | CUnary       CUnaryOp CExpr+  | CSizeOfExpr  CExpr+  | CSizeOfType  CDecl+  | CIndex       CExpr CExpr+  | CCall        CExpr [CExpr]+  | CMember      CExpr Ident Bool+  | CVar         Ident+  | CConstant    CConst+  | CCompoundLit CDecl CInit+  deriving (Show, Eq, Ord)+++data CAssignOp+  = CAssignOp+  | CMulAssOp+  | CDivAssOp+  | CRmdAssOp+  | CAddAssOp+  | CSubAssOp+  | CShlAssOp+  | CShrAssOp+  | CAndAssOp+  | CXorAssOp+  | COrAssOp+  deriving (Show, Eq, Ord)+++data CBinaryOp+  = CMulOp+  | CDivOp+  | CRmdOp+  | CAddOp+  | CSubOp+  | CShlOp+  | CShrOp+  | CLeOp+  | CGrOp+  | CLeqOp+  | CGeqOp+  | CEqOp+  | CNeqOp+  | CAndOp+  | CXorOp+  | COrOp+  | CLndOp+  | CLorOp+  deriving (Show, Eq, Ord)+++data CUnaryOp+  = CPreIncOp+  | CPreDecOp+  | CPostIncOp+  | CPostDecOp+  | CAdrOp+  | CIndOp+  | CPlusOp+  | CMinOp+  | CCompOp+  | CNegOp+  deriving (Show, Eq, Ord)+++data CConst+  = CIntConst    Integer+  | CCharConst   Char+  | CFloatConst  Float+  | CStringConst String+  deriving (Show, Eq, Ord)+++--------------------------------------------------------------------------------+--                      Infix and Smart Constructors                          --+--------------------------------------------------------------------------------+{-+  These are helpful when building up ASTs in Haskell code. They correspond to+  the concrete syntax of C. This is an incomplete set...+-}++seqCStat :: [CStat] -> CStat+seqCStat = CCompound . fmap CBlockStat++(.<.),(.>.),(.==.),(.||.),(.&&.),(.*.),(./.),(.-.),(.+.),(.=.),(.+=.),(.*=.),(.<=.),(.>=.)+  :: CExpr -> CExpr -> CExpr+a .<. b  = CBinary CLeOp a b+a .>. b  = CBinary CGrOp a b+a .==. b = CBinary CEqOp a b+a .||. b = CBinary CLorOp a b+a .&&. b = CBinary CAndOp a b+a .*. b  = CBinary CMulOp a b+a ./. b  = CBinary CDivOp a b+a .-. b  = CBinary CSubOp a b+a .+. b  = CBinary CAddOp a b+a .<=. b = CBinary CLeqOp a b+a .>=. b = CBinary CGeqOp a b+a .=. b  = CAssign CAssignOp a b+a .+=. b = CAssign CAddAssOp a b+a .*=. b = CAssign CMulAssOp a b++indirect, address :: CExpr -> CExpr+indirect = CUnary CIndOp+address  = CUnary CAdrOp++intE :: Integer -> CExpr+intE = CConstant . CIntConst++floatE :: Float -> CExpr+floatE = CConstant . CFloatConst++stringE :: String -> CExpr+stringE = CConstant . CStringConst++mkUnary :: String -> CExpr -> CExpr+mkUnary s = CCall (CVar . Ident $ s) . (:[])++--------------------------------------------------------------------------------+--                                 Lib C                                      --+--------------------------------------------------------------------------------+{-+  Here we have calls to a very small subset of functionality provided by libc.+  In the future, we should have a standard way to add in bindings to C+  libraries. Easily generating code for existing C libraries is one of the key+  design goals of pedantic-c+-}++------------+-- math.h --+------------++exp,expm1,log,log1p,sqrt :: CExpr -> CExpr+exp   = mkUnary "exp"+expm1 = mkUnary "expm1"+log   = mkUnary "log"+log1p = mkUnary "log1p"+sqrt  = mkUnary "sqrt"++infinityE,negInfinityE :: CExpr+infinityE    = (intE 1) ./. (intE 0)+negInfinityE = log (intE 0)++--------------+-- stdlib.h --+--------------++rand :: CExpr+rand = CCall (CVar . Ident $ "rand") []++--------------+-- stdlio.h --+--------------++printfE :: [CExpr] -> CExpr+printfE = CCall (CVar . Ident $ "printf")
+ haskell/Language/Hakaru/CodeGen/CodeGenMonad.hs view
@@ -0,0 +1,364 @@+{-# LANGUAGE CPP,+             BangPatterns,+             DataKinds,+             FlexibleContexts,+             FlexibleInstances,+             GADTs,+             KindSignatures,+             PolyKinds,+             StandaloneDeriving,+             TypeOperators,+             RankNTypes        #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++----------------------------------------------------------------+--                                                    2016.07.01+-- |+-- Module      :  Language.Hakaru.CodeGen.CodeGenMonad+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  zsulliva@indiana.edu+-- Stability   :  experimental+-- Portability :  GHC-only+--+--   This module provides a monad for C code generation as well+-- as some useful helper functions for manipulating it+----------------------------------------------------------------+++module Language.Hakaru.CodeGen.CodeGenMonad+  ( CodeGen+  , CG(..)+  , runCodeGen+  , runCodeGenBlock+  , runCodeGenWith+  , emptyCG+  , suffixes++  -- codegen effects+  , declare+  , declare'+  , assign+  , putStat+  , putExprStat+  , extDeclare+  , defineFunction+  , funCG+  , isParallel+  , mkParallel+  , mkSequential++  , reserveName+  , genIdent+  , genIdent'++  -- Hakaru specific+  , createIdent+  , lookupIdent++  -- control mechanisms+  , whileCG+  , doWhileCG+  , forCG+  , reductionCG+  ) where++import Control.Monad.State.Strict++#if __GLASGOW_HASKELL__ < 710+import Data.Monoid (Monoid(..))+import Control.Applicative ((<$>))+#endif++import Language.Hakaru.Syntax.ABT hiding (var)+import Language.Hakaru.Types.DataKind+import Language.Hakaru.Types.Sing+import Language.Hakaru.CodeGen.Types+import Language.Hakaru.CodeGen.AST+import Language.Hakaru.CodeGen.Pretty++import Data.Number.Nat (fromNat)+import qualified Data.IntMap.Strict as IM+import qualified Data.Text          as T+import qualified Data.Set           as S++import Text.PrettyPrint (render)++suffixes :: [String]+suffixes = filter (\n -> not $ elem (head n) ['0'..'9']) names+  where base :: [Char]+        base = ['0'..'9'] ++ ['a'..'z']+        names = [[x] | x <- base] `mplus` (do n <- names+                                              [n++[x] | x <- base])++-- CG after "codegen", holds the state of a codegen computation+data CG = CG { freshNames    :: [String]     -- ^ fresh names for code generations+             , reservedNames :: S.Set String -- ^ reserve names during code generations+             , extDecls      :: [CExtDecl]   -- ^ total external declarations+             , declarations  :: [CDecl]      -- ^ declarations in local block+             , statements    :: [CStat]      -- ^ statements can include assignments as well as other side-effects+             , varEnv        :: Env          -- ^ mapping between Hakaru vars and codegeneration vars+             , parallel      :: Bool         -- ^ openMP supported block+             }++emptyCG :: CG+emptyCG = CG suffixes mempty mempty [] [] emptyEnv False++type CodeGen = State CG++runCodeGen :: CodeGen a -> ([CExtDecl],[CDecl], [CStat])+runCodeGen m =+  let (_, cg) = runState m emptyCG+  in  ( reverse $ extDecls     cg+      , reverse $ declarations cg+      , reverse $ statements   cg )+++runCodeGenBlock :: CodeGen a -> CodeGen CStat+runCodeGenBlock m =+  do cg <- get+     let (_,cg') = runState m $ cg { statements = []+                                   , declarations = [] }+     put $ cg' { statements   = statements cg+               , declarations = declarations cg' ++ declarations cg+               }+     return . CCompound . fmap CBlockStat . reverse . statements $ cg'++runCodeGenWith :: CodeGen a -> CG -> [CExtDecl]+runCodeGenWith cg start = let (_,cg') = runState cg start in reverse $ extDecls cg'++--------------------------------------------------------------------------------++isParallel :: CodeGen Bool+isParallel = parallel <$> get++mkParallel :: CodeGen ()+mkParallel =+  do cg <- get+     put (cg { parallel = True } )++mkSequential :: CodeGen ()+mkSequential =+  do cg <- get+     put (cg { parallel = False } )++--------------------------------------------------------------------------------++reserveName :: String -> CodeGen ()+reserveName s =+  get >>= \cg -> put $ cg { reservedNames = s `S.insert` reservedNames cg }+++genIdent :: CodeGen Ident+genIdent =+  do cg <- get+     let (freshNs,name) = pullName (freshNames cg) (reservedNames cg)+     put $ cg { freshNames = freshNs }+     return $ Ident name+  where pullName :: [String] -> S.Set String -> ([String],String)+        pullName (n:names) reserved =+          let name = "_" ++ n in+          if S.member name reserved+          then let (names',out) = pullName names reserved+               in  (n:names',out)+          else (names,name)+        pullName _ _ = error "should not happen, names is infinite"++genIdent' :: String -> CodeGen Ident+genIdent' s =+  do cg <- get+     let (freshNs,name) = pullName (freshNames cg) (reservedNames cg)+     put $ cg { freshNames = freshNs }+     return $ Ident name+  where pullName :: [String] -> S.Set String -> ([String],String)+        pullName (n:names) reserved =+          let name = s ++ "_" ++ n in+          if S.member name reserved+          then let (names',out) = pullName names reserved+               in  (n:names',out)+          else (names,name)+        pullName _ _ = error "should not happen, names is infinite"++++createIdent :: Variable (a :: Hakaru) -> CodeGen Ident+createIdent var@(Variable name _ _) =+  do !cg <- get+     let ident = Ident $ (T.unpack name) ++ "_" ++ (head $ freshNames cg)+         env'  = updateEnv var ident (varEnv cg)+     put $! cg { freshNames = tail $ freshNames cg+               , varEnv     = env' }+     return ident++lookupIdent :: Variable (a :: Hakaru) -> CodeGen Ident+lookupIdent var =+  do !cg <- get+     let !env = varEnv cg+     case lookupVar var env of+       Nothing -> error $ "lookupIdent: var not found --" ++ show var+       Just i  -> return i++-- | types like SData and SMeasure are impure in that they will produce extra+--   code in the CodeGenMonad while literal types SReal, SInt, SNat, and SProb+--   do not+declare :: Sing (a :: Hakaru) -> Ident -> CodeGen ()+declare SInt          = declare' . typeDeclaration SInt+declare SNat          = declare' . typeDeclaration SNat+declare SProb         = declare' . typeDeclaration SProb+declare SReal         = declare' . typeDeclaration SReal+declare (SMeasure (SArray t))  = \i -> do extDeclare $ arrayStruct t+                                          extDeclare $ mdataStruct t+                                          declare'   $ mdataDeclaration (SArray t) i+declare (SMeasure t)  = \i -> do extDeclare $ mdataStruct t+                                 declare'   $ mdataDeclaration t i+declare (SArray t)    = \i -> do extDeclare $ arrayStruct t+                                 declare'   $ arrayDeclaration t i+declare d@(SData _ _) = \i -> do extDeclare $ datumStruct d+                                 declare'   $ datumDeclaration d i+declare (SFun _ _)    = \_ -> return () -- function definitions handeled in flatten+++declare' :: CDecl -> CodeGen ()+declare' d = do cg <- get+                put $ cg { declarations = d:(declarations cg) }++putStat :: CStat -> CodeGen ()+putStat s = do cg <- get+               put $ cg { statements = s:(statements cg) }++putExprStat :: CExpr -> CodeGen ()+putExprStat = putStat . CExpr . Just++assign :: Ident -> CExpr -> CodeGen ()+assign ident e = putStat . CExpr . Just $ (CVar ident .=. e)+++extDeclare :: CExtDecl -> CodeGen ()+extDeclare d = do cg <- get+                  let extds = extDecls cg+                      extds' = if elem d extds+                               then extds+                               else d:extds+                  put $ cg { extDecls = extds' }++defineFunction :: Sing (a :: Hakaru) -> Ident -> [CDecl] -> CodeGen () -> CodeGen ()+defineFunction typ ident args mbody =+  do cg <- get+     mbody+     !cg' <- get+     let decls = reverse . declarations $ cg'+         stmts = reverse . statements   $ cg'+         def :: Sing (a :: Hakaru) -> CFunDef+         def SInt         = functionDef SInt  ident args decls stmts+         def SNat         = functionDef SNat  ident args decls stmts+         def SProb        = functionDef SProb ident args decls stmts+         def SReal        = functionDef SReal ident args decls stmts+         def (SMeasure t) = functionDef (SMeasure t) ident args decls stmts+         def t            = error $ "TODO: defined function of type: " ++ show t++     -- reset local statements and declarations+     put $ cg' { statements   = statements cg+               , declarations = declarations cg }+     extDeclare . CFunDefExt $ def typ++funCG :: CTypeSpec -> Ident -> [CDecl] -> CodeGen () -> CodeGen ()+funCG ts ident args mbody =+  do cg <- get+     mbody+     !cg' <- get+     let decls = reverse . declarations $ cg'+         stmts = reverse . statements   $ cg'+     -- reset local statements and declarations+     put $ cg' { statements   = statements cg+               , declarations = declarations cg }+     extDeclare . CFunDefExt $+       CFunDef [CTypeSpec ts]+               (CDeclr Nothing [ CDDeclrIdent ident ])+               args+               (CCompound ((fmap CBlockDecl decls) ++ (fmap CBlockStat stmts)))+++++---------+-- ENV --+---------++newtype Env = Env (IM.IntMap Ident)+  deriving Show++emptyEnv :: Env+emptyEnv = Env IM.empty++updateEnv :: Variable (a :: Hakaru) -> Ident -> Env -> Env+updateEnv (Variable _ nat _) ident (Env env) =+  Env $! IM.insert (fromNat nat) ident env++lookupVar :: Variable (a :: Hakaru) -> Env -> Maybe Ident+lookupVar (Variable _ nat _) (Env env) =+  IM.lookup (fromNat nat) env++----------------------------------------------------------------+-- Control Flow++whileCG :: CExpr -> CodeGen () -> CodeGen ()+whileCG bE m =+  let (_,_,stmts) = runCodeGen m+  in putStat $ CWhile bE (CCompound $ fmap CBlockStat stmts) False++doWhileCG :: CExpr -> CodeGen () -> CodeGen ()+doWhileCG bE m =+  let (_,_,stmts) = runCodeGen m+  in putStat $ CWhile bE (CCompound $ fmap CBlockStat stmts) True++-- forCG and reductionCG both create C for loops, their difference lies in the+-- parallel code they generate++forCG+  :: CExpr+  -> CExpr+  -> CExpr+  -> CodeGen ()+  -> CodeGen ()+forCG iter cond inc body =+  do cg <- get+     let (_,cg') = runState body $ cg { statements = []+                                      , declarations = [] }+     put $ cg' { statements = statements cg+               , declarations = declarations cg }+     par <- isParallel+     when par . putStat . CPPStat . PPPragma+       $ ["omp","parallel","for"]+     putStat $ CFor (Just iter)+                    (Just cond)+                    (Just inc)+                    (CCompound $  (fmap CBlockDecl (reverse $ declarations cg')+                               ++ (fmap CBlockStat (reverse $ statements cg'))))++reductionCG+  :: CBinaryOp+  -> Ident+  -> CExpr+  -> CExpr+  -> CExpr+  -> CodeGen ()+  -> CodeGen ()+reductionCG op acc iter cond inc body =+  do cg <- get+     let (_,cg') = runState body $ cg { statements = []+                                      , declarations = [] }+     put $ cg' { statements = statements cg+               , declarations = declarations cg }+     par <- isParallel+     when par . putStat . CPPStat . PPPragma+       $ ["omp","parallel","for"+         , concat ["reduction("+                  ,render . pretty $ op+                  ,":"+                  ,render . pretty $ acc+                  ,")"]]+     putStat $ CFor (Just iter)+                    (Just cond)+                    (Just inc)+                    (CCompound $  (fmap CBlockDecl (reverse $ declarations cg')+                               ++ (fmap CBlockStat (reverse $ statements cg'))))
+ haskell/Language/Hakaru/CodeGen/Flatten.hs view
@@ -0,0 +1,1244 @@+{-# LANGUAGE CPP,+             BangPatterns,+             DataKinds,+             FlexibleContexts,+             GADTs,+             KindSignatures,+             ScopedTypeVariables,+             RankNTypes,+             TypeOperators #-}++----------------------------------------------------------------+--                                                    2016.06.23+-- |+-- Module      :  Language.Hakaru.CodeGen.Flatten+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  zsulliva@indiana.edu+-- Stability   :  experimental+-- Portability :  GHC-only+--+--   Flatten takes Hakaru ABTs and C vars and returns a CStatement+-- assigning the var to the flattened ABT.+--+----------------------------------------------------------------+++module Language.Hakaru.CodeGen.Flatten+  ( flattenABT+  , flattenVar+  , flattenTerm )+  where++import Language.Hakaru.CodeGen.CodeGenMonad+import Language.Hakaru.CodeGen.AST+import Language.Hakaru.CodeGen.Types++import Language.Hakaru.Syntax.AST+import Language.Hakaru.Syntax.ABT+import Language.Hakaru.Syntax.TypeOf (typeOf)+import Language.Hakaru.Syntax.Datum hiding (Ident)+import qualified Language.Hakaru.Syntax.Prelude as HKP+import Language.Hakaru.Types.DataKind+import Language.Hakaru.Types.HClasses+import Language.Hakaru.Types.Coercion+import Language.Hakaru.Types.Sing++import           Control.Monad.State.Strict+import           Control.Monad (replicateM)+import           Data.Number.Natural+import           Data.Ratio+import qualified Data.List.NonEmpty as NE+import qualified Data.Sequence      as S+import qualified Data.Foldable      as F+import qualified Data.Traversable   as T+++#if __GLASGOW_HASKELL__ < 710+import           Data.Functor+#endif++import Prelude hiding (log,exp,sqrt)+++opComment :: String -> CStat+opComment opStr = CComment $ concat [space," ",opStr," ",space]+  where size  = (50 - (length opStr)) `div` 2 - 8+        space = replicate size '-'++--------------------------------------------------------------------------------+--                                 Top Level                                  --+--------------------------------------------------------------------------------+{-++flattening an ABT will produce a continuation that takes a CExpr representing+a location where the value of the ABT should be stored. Return type of the+the continuation is CodeGen Bool, where the computed bool is whether or not+there is a Reject inside the ABT. Therefore it is only needed when computing+mochastic values++-}++flattenABT+  :: ABT Term abt+  => abt '[] a+  -> (CExpr -> CodeGen ())+flattenABT abt = caseVarSyn abt flattenVar flattenTerm++-- note that variables will find their values in the state of the CodeGen monad+flattenVar+  :: Variable (a :: Hakaru)+  -> (CExpr -> CodeGen ())+flattenVar v = \loc ->+  do v' <- CVar <$> lookupIdent v+     putStat . CExpr . Just $ loc .=. v'++flattenTerm+  :: ABT Term abt+  => Term abt a+  -> (CExpr -> CodeGen ())+flattenTerm (NaryOp_ t s)    = flattenNAryOp t s+flattenTerm (Literal_ x)     = flattenLit x+flattenTerm (Empty_ _)       = error "TODO: flattenTerm Empty"++flattenTerm (Datum_ d)       = flattenDatum d+flattenTerm (Case_ c bs)     = flattenCase c bs++flattenTerm (Array_ s e)     = flattenArray s e++-- SCon can contain mochastic terms+flattenTerm (x :$ ys)        = flattenSCon x ys++---------------------+-- Mochastic Terms --+---------------------+flattenTerm (Reject_ _)      = \loc -> putExprStat (mdataPtrWeight loc .=. (intE 0)) -- fail to draw a sample+flattenTerm (Superpose_ wes) = flattenSuperpose wes++++++--------------------------------------------------------------------------------+--                                  SCon                                      --+--------------------------------------------------------------------------------++flattenSCon+  :: ( ABT Term abt )+  => SCon args a+  -> SArgs abt args+  -> (CExpr -> CodeGen ())++flattenSCon Let_ =+  \(expr :* body :* End) ->+    \loc -> do+      caseBind body $ \v@(Variable _ _ typ) body'->+        do ident <- createIdent v+           declare typ ident+           flattenABT expr (CVar ident)+           flattenABT body' loc++-- Lambdas produce functions and then return a function pointer+flattenSCon Lam_ = undefined+  -- \(body :* End) ->+  --   \loc ->+  --     do coalesceLambda body $ \vars body' ->+  --        let varMs = foldMap11 (\v -> [mkVarDecl v =<< createIdent v]) vars+  --        in  do funcId <- genIdent' "fn"+  --               argDecls <- sequence varMs++  --               cg <- get+  --               let m       = putStat . CReturn . Just =<< flattenABT body'+  --                   (_,cg') = runState m $ cg { statements = []+  --                                             , declarations = [] }+  --               put $ cg' { statements   = statements cg+  --                         , declarations = declarations cg }++  --               extDeclare . CFunDefExt $ functionDef (typeOf body')+  --                                                     funcId+  --                                                     argDecls+  --                                                     (reverse $ declarations cg')+  --                                                     (reverse $ statements cg')+  -- -- do at top level+  -- where coalesceLambda+  --         :: ( ABT Term abt )+  --         => abt '[x] a+  --         -> (forall (ys :: [Hakaru]) b. List1 Variable ys -> abt '[] b -> r)+  --         -> r+  --       coalesceLambda abt k =+  --         caseBind abt $ \v abt' ->+  --           caseVarSyn abt' (const (k (Cons1 v Nil1) abt')) $ \term ->+  --             case term of+  --               (Lam_ :$ body :* End) ->+  --                 coalesceLambda body $ \vars abt'' -> k (Cons1 v vars) abt''+  --               _ -> k (Cons1 v Nil1) abt'++  --       mkVarDecl :: Variable (a :: Hakaru) -> Ident -> CodeGen CDecl+  --       mkVarDecl (Variable _ _ SInt)  = return . typeDeclaration SInt+  --       mkVarDecl (Variable _ _ SNat)  = return . typeDeclaration SNat+  --       mkVarDecl (Variable _ _ SProb) = return . typeDeclaration SProb+  --       mkVarDecl (Variable _ _ SReal) = return . typeDeclaration SReal+  --       mkVarDecl (Variable _ _ (SArray t)) = \i -> do extDeclare $ arrayStruct t+  --                                                      return $ arrayDeclaration t i+  --       mkVarDecl (Variable _ _ d@(SData _ _)) = \i -> do extDeclare $ datumStruct d+  --                                                         return $ datumDeclaration d i+  --       mkVarDecl v = error $ "flattenSCon.Lam_.mkVarDecl cannot handle vars of type " ++ show v+++flattenSCon (PrimOp_ op) = flattenPrimOp op++flattenSCon (ArrayOp_ op) = flattenArrayOp op++flattenSCon (Summate _ sr) =+  \(lo :* hi :* body :* End) ->+    \loc ->+      caseBind body $ \v body' ->+        do loId <- genIdent+           hiId <- genIdent+           declare (typeOf lo) loId+           declare (typeOf hi) hiId+           let loE = CVar loId+               hiE = CVar hiId+           flattenABT lo loE+           flattenABT hi hiE++           iterI <- createIdent v+           declare SNat iterI++           accI <- genIdent' "acc"+           let semiT = sing_HSemiring sr+           declare semiT accI+           assign accI (case semiT of+                          SProb -> negInfinityE+                          SReal -> floatE 0+                          _     -> intE 0)++           let accVar  = CVar accI+               iterVar = CVar iterI+++           putStat $ opComment "Summate"+           -- logSumExp for probabilities+           reductionCG CAddOp+                       accI+                       (iterVar .=. loE)+                       (iterVar .<. hiE)+                       (CUnary CPostIncOp iterVar) $+             do tmpId <- genIdent+                declare (typeOf body') tmpId+                let tmpE = CVar tmpId+                flattenABT body' tmpE+                case semiT of+                  SProb -> logSumExpCG (S.fromList [accVar,tmpE]) accVar+                  _     -> putStat . CExpr . Just $ (accVar .+=. tmpE)++           putExprStat (loc .=. accVar)+++flattenSCon (Product _ sr) =+  \(lo :* hi :* body :* End) ->+    \loc ->+      caseBind body $ \v body' ->+        do loId <- genIdent+           hiId <- genIdent+           declare (typeOf lo) loId+           declare (typeOf hi) hiId+           let loE = CVar loId+               hiE = CVar hiId+           flattenABT lo loE+           flattenABT hi hiE++           iterI <- createIdent v+           declare SNat iterI++           accI <- genIdent' "acc"+           let semiT = sing_HSemiring sr+           declare semiT accI+           assign accI (case semiT of+                          SProb -> floatE 0+                          SReal -> floatE 1+                          _     -> intE 1)++           let accVar  = CVar accI+               iterVar = CVar iterI++           putStat $ opComment "Product"+           reductionCG (case semiT of+                          SProb -> CAddOp+                          _     -> CMulOp)+                       accI+                       (iterVar .=. loE)+                       (iterVar .<. hiE)+                       (CUnary CPostIncOp iterVar) $+             do tmpId <- genIdent+                declare (typeOf body') tmpId+                let tmpE = CVar tmpId+                flattenABT body' tmpE+                putExprStat $ case semiT of+                                SProb -> CAssign CAddAssOp accVar+                                _ -> CAssign CMulAssOp accVar+                            $ tmpE++           putExprStat (loc .=. accVar)+++--------------------+-- SCon Coersions --+--------------------++-- at this point, only nonrecusive coersions are implemented+flattenSCon (CoerceTo_ ctyp) =+  \(e :* End) ->+    \loc ->+       do eId <- genIdent+          let eT = typeOf e+              eE = CVar eId+          declare eT eId+          flattenABT e eE+          putExprStat . (CAssign CAssignOp loc) =<< coerceToType ctyp eT eE+  where coerceToType+          :: Coercion a b+          -> Sing (c :: Hakaru)+          -> CExpr+          -> CodeGen CExpr+        coerceToType (CCons p rest) typ =+          \e ->  primitiveCoerce p typ e >>= coerceToType rest typ+        coerceToType CNil            _  = return . id++        primitiveCoerce+          :: PrimCoercion a b+          -> Sing (c :: Hakaru)+          -> CExpr+          -> CodeGen CExpr+        primitiveCoerce (Signed HRing_Int)            SNat  = nat2int+        primitiveCoerce (Signed HRing_Real)           SProb = prob2real+        primitiveCoerce (Continuous HContinuous_Prob) SNat  = nat2prob+        primitiveCoerce (Continuous HContinuous_Real) SInt  = int2real+        primitiveCoerce (Continuous HContinuous_Real) SNat  = int2real+        primitiveCoerce a b = error $ "flattenSCon CoerceTo_: cannot preform coersion "+                                    ++ show a+                                    ++ " to "+                                    ++ show b+++        -- implementing ONLY functions found in Hakaru.Syntax.AST+        nat2int,nat2prob,prob2real,int2real+          :: CExpr -> CodeGen CExpr+        nat2int   = return+        nat2prob  = \n -> do ident <- genIdent' "p"+                             declare SProb ident+                             assign ident . log1p $ n .-. (intE 1)+                             return (CVar ident)+        prob2real = \p -> do ident <- genIdent' "r"+                             declare SReal ident+                             assign ident $ (expm1 p) .+. (intE 1)+                             return (CVar ident)+        int2real  = return . CCast doubleDecl+++-----------------------------------+-- SCons in the Stochastic Monad --+-----------------------------------++flattenSCon (MeasureOp_ op) = flattenMeasureOp op++flattenSCon Dirac           =+  \(e :* End) ->+    \loc ->+       do sId <- genIdent' "samp"+          declare (typeOf e) sId+          let sE = CVar sId+          flattenABT e sE+          putExprStat $ mdataPtrWeight loc .=. (floatE 0)+          putExprStat $ mdataPtrSample loc .=. sE++flattenSCon MBind           =+  \(ma :* b :* End) ->+    \loc ->+      caseBind b $ \v@(Variable _ _ typ) mb ->+        do -- first+           mId <- genIdent' "m"+           declare (typeOf ma) mId+           let mE = CVar mId+           flattenABT ma (address mE)++           -- assign that sample to var+           vId <- createIdent v+           declare typ vId+           assign vId (mdataSample mE)+           flattenABT mb loc+           putExprStat $ mdataPtrWeight loc .+=. (mdataWeight mE)++-- for now plats make use of a global sample+flattenSCon Plate           =+  \(size :* b :* End) ->+    \loc ->+      caseBind b $ \v@(Variable _ _ typ) body ->+        do sizeId <- genIdent' "s"+           declare SNat sizeId+           let sizeE = CVar sizeId+           flattenABT size sizeE+           putExprStat $   (arrayPtrData . mdataPtrSample $ loc)+                       .=. (CCast (mkPtrDecl . buildType $ typ)+                                  (mkUnary "malloc"+                                  (sizeE .*. (CSizeOfType . mkDecl . buildType $ typ))))++++           weightId <- genIdent' "w"+           declare SProb weightId+           let weightE = CVar weightId+           assign weightId (floatE 0)++           itId <- createIdent v+           declare SNat itId+           let itE = CVar itId+               currInd  = indirect $ (CMember (mdataSample loc) (Ident "data") True) .+. itE++           sampId <- genIdent' "samp"+           declare (typeOf $ body) sampId+           let sampE = CVar sampId++           reductionCG CAddOp+                       weightId+                       (itE .=. (intE 0))+                       (itE .<. sizeE)+                       (CUnary CPostIncOp itE)+                       (do flattenABT body (address sampE)+                           putExprStat (currInd .=. (mdataSample sampE))+                           putExprStat (weightE .+=. (mdataWeight sampE)))++           putExprStat $ mdataPtrWeight loc .=. weightE+++-----------------------------------+-- SCon's that arent implemented --+-----------------------------------++flattenSCon x               = \_ -> \_ -> error $ "TODO: flattenSCon: " ++ show x++++++--------------------------------------------------------------------------------+--                                 NaryOps                                    --+--------------------------------------------------------------------------------++flattenNAryOp :: ABT Term abt+              => NaryOp a+              -> S.Seq (abt '[] a)+              -> (CExpr -> CodeGen ())+flattenNAryOp op args =+  \loc ->+    do es <- T.forM args $ \a ->+               do aId <- genIdent+                  let aE = CVar aId+                  declare (typeOf a) aId+                  _ <- flattenABT a aE+                  return aE+       case op of+         And -> boolNaryOp op es loc+         Or  -> boolNaryOp op es loc+         Xor -> boolNaryOp op es loc+         Iff -> boolNaryOp op es loc++         (Sum HSemiring_Prob) -> logSumExpCG es loc++         _ -> let opE = F.foldr (binaryOp op) (S.index es 0) (S.drop 1 es)+              in  putExprStat (loc .=. opE)+++  where boolNaryOp op' es' loc' =+          let indexOf x = CMember x (Ident "index") True+              es''      = fmap indexOf es'+              expr      = F.foldr (binaryOp op')+                                  (S.index es'' 0)+                                  (S.drop 1 es'')+          in  putExprStat ((indexOf loc') .=. expr)+++--------------------------------------+-- LogSumExp for NaryOp Add [SProb] --+--------------------------------------+{-++Special for addition of probabilities we have a logSumExp. This will compute the+sum of the probabilities safely. Just adding the exp(a . prob) would make us+loose any of the safety from underflow that we got from storing prob in the log+domain++-}++-- the tree traversal is a depth first search+logSumExp :: S.Seq CExpr -> CExpr+logSumExp es = mkCompTree 0 1++  where lastIndex  = S.length es - 1++        compIndices :: Int -> Int -> CExpr -> CExpr -> CExpr+        compIndices i j = CCond ((S.index es i) .>. (S.index es j))++        mkCompTree :: Int -> Int -> CExpr+        mkCompTree i j+          | j == lastIndex = compIndices i j (logSumExp' i) (logSumExp' j)+          | otherwise      = compIndices i j+                               (mkCompTree i (succ j))+                               (mkCompTree j (succ j))++        diffExp :: Int -> Int -> CExpr+        diffExp a b = expm1 ((S.index es a) .-. (S.index es b))++        -- given the max index, produce a logSumExp expression+        logSumExp' :: Int -> CExpr+        logSumExp' 0 = S.index es 0+          .+. (log1p $ foldr (\x acc -> diffExp x 0 .+. acc)+                            (diffExp 1 0)+                            [2..S.length es - 1]+                    .+. (intE $ fromIntegral lastIndex))+        logSumExp' i = S.index es i+          .+. (log1p $ foldr (\x acc -> if i == x+                                       then acc+                                       else diffExp x i .+. acc)+                            (diffExp 0 i)+                            [1..S.length es - 1]+                    .+. (intE $ fromIntegral lastIndex))+++-- | logSumExpCG creates global functions for every n-ary logSumExp function+-- this reduces code size+logSumExpCG :: S.Seq CExpr -> (CExpr -> CodeGen ())+logSumExpCG seqE =+  let size   = S.length $ seqE+      name   = "logSumExp" ++ (show size)+      funcId = Ident name+  in \loc -> do-- reset the names so that the function is the same for each arity+       cg <- get+       put (cg { freshNames = suffixes })+       argIds <- replicateM size genIdent+       let decls = fmap (typeDeclaration SProb) argIds+           vars  = fmap CVar argIds+       extDeclare . CFunDefExt $ functionDef SProb+                                             funcId+                                             decls+                                             []+                                             [CReturn . Just $ logSumExp $ S.fromList vars ]+       cg' <- get+       put (cg' { freshNames = freshNames cg })+       putExprStat $ loc .=. (CCall (CVar funcId) (F.toList seqE))+++--------------------------------------------------------------------------------+--                                  Literals                                  --+--------------------------------------------------------------------------------++flattenLit+  :: Literal a+  -> (CExpr -> CodeGen ())+flattenLit lit =+  \loc ->+    case lit of+      (LNat x)  -> putExprStat $ loc .=. (intE $ fromIntegral x)+      (LInt x)  -> putExprStat $ loc .=. (intE x)+      (LReal x) -> putExprStat $ loc .=. (floatE $ fromRational x)+      (LProb x) -> let rat = fromNonNegativeRational x+                       x'  = (fromIntegral $ numerator rat)+                           / (fromIntegral $ denominator rat)+                       xE  = log1p (floatE x' .-. intE 1)+                   in putExprStat (loc .=. xE)++--------------------------------------------------------------------------------+--                                Array and ArrayOps                          --+--------------------------------------------------------------------------------+++flattenArray+  :: (ABT Term abt)+  => (abt '[] 'HNat)+  -> (abt '[ 'HNat ] a)+  -> (CExpr -> CodeGen ())+flattenArray arity body =+  \loc ->+    caseBind body $ \v@(Variable _ _ typ) body' ->+      let arityE = arraySize loc+          dataE  = arrayData loc in+      do flattenABT arity arityE+         putExprStat $   dataE+                     .=. (CCast (mkPtrDecl . buildType $ typ)+                                (mkUnary "malloc"+                                  (arityE .*. (CSizeOfType . mkDecl . buildType $ typ))))++         itId  <- createIdent v+         declare SNat itId+         let itE     = CVar itId+             currInd = indirect (dataE .+. itE)++         putStat $ opComment "Create Array"+         forCG (itE .=. (intE 0))+               (itE .<. arityE)+               (CUnary CPostIncOp itE)+               (flattenABT body' currInd)+++--------------+-- ArrayOps --+--------------++flattenArrayOp+  :: ( ABT Term abt+     , typs ~ UnLCs args+     , args ~ LCs typs+     )+  => ArrayOp typs a+  -> SArgs abt args+  -> (CExpr -> CodeGen ())+++flattenArrayOp (Index _)  =+  \(arr :* ind :* End) ->+    \loc ->+      do arrId <- genIdent' "arr"+         indId <- genIdent+         let arrE = CVar arrId+             indE = CVar indId+         declare (typeOf arr) arrId+         declare SNat indId+         flattenABT arr arrE+         flattenABT ind indE+         let valE = indirect ((CMember arrE (Ident "data") True) .+. indE)+         putExprStat (loc .=. valE)++flattenArrayOp (Size _)   =+  \(arr :* End) ->+    \loc ->+      do arrId <- genIdent' "arr"+         declare (typeOf arr) arrId+         let arrE = CVar arrId+         flattenABT arr arrE+         putExprStat (loc .=. (CMember arrE (Ident "size") True))++flattenArrayOp (Reduce _) = error "TODO: flattenArrayOp"+  -- \(fun :* base :* arr :* End) ->+  -- do funE  <- flattenABT fun+  --    baseE <- flattenABT base+  --    arrE  <- flattenABT arr+  --    accI  <- genIdent' "acc"+  --    iterI <- genIdent' "iter"++  --    let sizeE = CMember arrE (Ident "size") True+  --        iterE = CVar iterI+  --        accE  = CVar accI+  --        cond  = iterE .<. sizeE+  --        inc   = CUnary CPostIncOp iterE++  --    declare (typeOf base) accI+  --    declare SInt iterI+  --    assign accI baseE+  --    forCG (iterE .=. (intE 0)) cond inc $+  --      assign accI $ CCall funE [accE]++  --    return accE+++--------------------------------------------------------------------------------+--                                 Datum and Case                             --+--------------------------------------------------------------------------------+{-++Datum are sums of products of types. This maps to a C structure. flattenDatum+will produce a literal of some datum type. This will also produce a global+struct representing that datum which will be needed for the C compiler.++-}+++flattenDatum+  :: (ABT Term abt)+  => Datum (abt '[]) (HData' a)+  -> (CExpr -> CodeGen ())+flattenDatum (Datum _ typ code) =+  \loc ->+    do extDeclare $ datumStruct typ+       assignDatum code loc++datumNames :: [String]+datumNames = filter (\n -> not $ elem (head n) ['0'..'9']) names+  where base = ['0'..'9'] ++ ['a'..'z']+        names = [[x] | x <- base] `mplus` (do n <- names+                                              [n++[x] | x <- base])++assignDatum+  :: (ABT Term abt)+  => DatumCode xss (abt '[]) c+  -> CExpr+  -> CodeGen ()+assignDatum code ident =+  let index     = getIndex code+      indexExpr = CMember ident (Ident "index") True+  in  do putExprStat (indexExpr .=. (intE index))+         sequence_ $ assignSum code ident+  where getIndex :: DatumCode xss b c -> Integer+        getIndex (Inl _)    = 0+        getIndex (Inr rest) = succ (getIndex rest)++assignSum+  :: (ABT Term abt)+  => DatumCode xs (abt '[]) c+  -> CExpr+  -> [CodeGen ()]+assignSum code ident = fst $ runState (assignSum' code ident) datumNames++assignSum'+  :: (ABT Term abt)+  => DatumCode xs (abt '[]) c+  -> CExpr+  -> State [String] [CodeGen ()]+assignSum' (Inr rest) topIdent =+  do (_:names) <- get+     put names+     assignSum' rest topIdent+assignSum' (Inl prod) topIdent =+  do (name:_) <- get+     return $ assignProd prod topIdent (CVar . Ident $ name)++assignProd+  :: (ABT Term abt)+  => DatumStruct xs (abt '[]) c+  -> CExpr+  -> CExpr+  -> [CodeGen ()]+assignProd dstruct topIdent sumIdent =+  fst $ runState (assignProd' dstruct topIdent sumIdent) datumNames++assignProd'+  :: (ABT Term abt)+  => DatumStruct xs (abt '[]) c+  -> CExpr+  -> CExpr+  -> State [String] [CodeGen ()]+assignProd' Done _ _ = return []+assignProd' (Et (Konst d) rest) topIdent (CVar sumIdent) =+  do (name:names) <- get+     put names+     let varName  = CMember (CMember (CMember topIdent+                                              (Ident "sum")+                                              True)+                                     sumIdent+                                     True)+                            (Ident name)+                            True+     rest' <- assignProd' rest topIdent (CVar sumIdent)+     return $ [flattenABT d varName] ++ rest'+assignProd' _ _ _  = error $ "TODO: assignProd Ident"+++----------+-- Case --+----------++-- currently we can only match on boolean values+flattenCase+  :: forall abt a b+  .  (ABT Term abt)+  => abt '[] a+  -> [Branch a abt b]+  -> (CExpr -> CodeGen ())++flattenCase c (Branch (PDatum _ (PInl PDone)) trueB:Branch (PDatum _ (PInr (PInl PDone))) falseB:[]) =+  \loc ->+    do cId <- genIdent+       declare (typeOf c) cId+       let cE = (CVar cId)+       flattenABT c cE++       cg <- get+       let trueM    = flattenABT trueB loc+           falseM   = flattenABT falseB loc+           (_,cg')  = runState trueM $ cg { statements = [] }+           (_,cg'') = runState falseM $ cg' { statements = [] }+       put $ cg'' { statements = statements cg }++       putStat $ CIf ((CMember cE (Ident "index") True) .==. (intE 0))+                     (CCompound . fmap CBlockStat . reverse . statements $ cg')+                     Nothing+       putStat $ CIf ((CMember cE (Ident "index") True) .==. (intE 1))+                     (CCompound . fmap CBlockStat . reverse . statements $ cg'')+                     Nothing+++flattenCase _ _ = error "TODO: flattenCase"+++--------------------------------------------------------------------------------+--                                     PrimOp                                 --+--------------------------------------------------------------------------------++flattenPrimOp+  :: ( ABT Term abt+     , typs ~ UnLCs args+     , args ~ LCs typs)+  => PrimOp typs a+  -> SArgs abt args+  -> (CExpr -> CodeGen ())+++flattenPrimOp Pi =+  \End ->+    \loc -> let piE = log1p ((CVar . Ident $ "M_PI") .-. (intE 1)) in+      putExprStat (loc .=. piE)++flattenPrimOp Not =+  \(a :* End) ->+    \_ ->+      -- this is currently incorrect, need to use memcpy to preserve value of+      -- 'a'+      do tmpId <- genIdent' "not"+         declare sBool tmpId+         let tmpE = CVar tmpId+         flattenABT a tmpE+         let datumIndex = CMember tmpE (Ident "index") True+         putExprStat $ datumIndex .=. (CCond (datumIndex .==. (intE 1))+                                             (intE 0)+                                             (intE 1))++flattenPrimOp RealPow =+  \(base :* power :* End) ->+    \loc ->+      do baseId <- genIdent+         powerId <- genIdent+         declare SProb baseId+         declare SReal powerId+         let baseE     = CVar baseId+             powerE = CVar powerId+         flattenABT base baseE -- first argument is a Prob+         flattenABT power powerE+         let realPow = CCall (CVar . Ident $ "pow")+                             [ expm1 baseE .+. (intE 1), powerE]+         putExprStat $ loc .=. (log1p (realPow .-. (intE 1)))++flattenPrimOp (NatPow baseTyp) =+  \(base :* power :* End) ->+    \loc ->+      let sBase = sing_HSemiring baseTyp in+      do baseId <- genIdent+         powerId <- genIdent+         declare sBase baseId+         declare SReal powerId+         let baseE     = CVar baseId+             powerE = CVar powerId+         flattenABT base baseE+         flattenABT power powerE+         let powerOf x y = CCall (CVar . Ident $ "pow") [x,y]+             value = case sBase of+                       SProb -> log1p $ (powerOf (expm1 baseE .+. (intE 1)) powerE)+                                  .-. (intE 1)+                       _     -> powerOf baseE powerE+         putExprStat $ loc .=. value++flattenPrimOp (NatRoot baseTyp) =+  \(base :* root :* End) ->+    \loc ->+      let sBase = sing_HRadical baseTyp in+      do baseId <- genIdent+         rootId <- genIdent+         declare sBase baseId+         declare SReal rootId+         let baseE = CVar baseId+             rootE = CVar rootId+         flattenABT base baseE+         flattenABT root rootE+         let powerOf x y = CCall (CVar . Ident $ "pow") [x,y]+             recipE = (floatE 1) ./. rootE+             value = case sBase of+                       SProb -> log1p $ (powerOf (expm1 baseE .+. (intE 1)) recipE)+                                      .-. (intE 1)+                       _     -> powerOf baseE recipE+         putExprStat $ loc .=. value++flattenPrimOp (Recip t) =+  \(a :* End) ->+    \loc ->+      do aId <- genIdent+         declare (typeOf a) aId+         let aE = CVar aId+         flattenABT a aE+         case t of+           HFractional_Real -> putExprStat $ loc .=. ((intE 1) ./. aE)+           HFractional_Prob -> putExprStat $ loc .=. (CUnary CMinOp aE)++-- | exp : real -> prob, because of this we can just turn it into a prob without taking+--   its log, which would give us an exp in the log-domain+flattenPrimOp Exp = \(a :* End) -> flattenABT a++flattenPrimOp (Equal _) =+  \(a :* b :* End) ->+    \loc ->+      do aId <- genIdent+         bId <- genIdent+         let aE = CVar aId+             bE = CVar bId+             aT = typeOf a+             bT = typeOf b+         declare aT aId+         declare bT bId+         flattenABT a aE+         flattenABT b bE++         -- special case for booleans+         let aE' = case aT of+                     (SData _ (SPlus SDone (SPlus SDone SVoid))) -> (CMember aE (Ident "index") True)+                     _ -> aE+         let bE' = case bT of+                     (SData _ (SPlus SDone (SPlus SDone SVoid))) -> (CMember bE (Ident "index") True)+                     _ -> bE++         putExprStat $   (CMember loc (Ident "index") True)+                     .=. (CCond (aE' .==. bE') (intE 0) (intE 1))+++flattenPrimOp (Less _) =+  \(a :* b :* End) ->+    \loc ->+      do aId <- genIdent+         bId <- genIdent+         let aE = CVar aId+             bE = CVar bId+         declare (typeOf a) aId+         declare (typeOf b) bId+         flattenABT a aE+         flattenABT b bE+         putExprStat $ (CMember loc (Ident "index") True)+                     .=. (CCond (aE .<. bE) (intE 0) (intE 1))++flattenPrimOp (Negate HRing_Real) =+ \(a :* End) ->+   \loc ->+     do negId <- genIdent' "neg"+        declare SReal negId+        let negE = CVar negId+        flattenABT a negE+        putExprStat $ loc .=. (CUnary CMinOp $ negE)+++flattenPrimOp t  = \_ -> error $ "TODO: flattenPrimOp: " ++ show t+++--------------------------------------------------------------------------------+--                           MeasureOps and Superpose                         --+--------------------------------------------------------------------------------++{-++The sections contains operations in the stochastic monad. See also+(Dirac, MBind, and Plate) found in SCon. Also see Reject found at the top level.++Remember in the C runtime. Measures are housed in a measure function, which+takes an `struct mdata` location. The MeasureOp attempts to store a value at+that location and returns 0 if it fails and 1 if it succeeds in that task.++The functions uniformCG, normalCG, and gammaCG are primitives that will generate+functions and call them (similar to logSumExpCG). The reduce code size and make+samplers a little more readable.++TODO: add inline pragmas to uniformCG, normalCG, and gammaCG+-}++uniformFun :: CFunDef+uniformFun = CFunDef [CTypeSpec CVoid]+                     (CDeclr Nothing [CDDeclrIdent funcId])+                     [typeDeclaration SReal loId+                     ,typeDeclaration SReal hiId+                     ,typePtrDeclaration (SMeasure SReal) mId]+                     (seqCStat $ comment ++[assW,assS,CReturn Nothing])+  where r          = CCast doubleDecl rand+        rMax       = CCast doubleDecl (CVar . Ident $ "RAND_MAX")+        (mId,mE)   = let ident = Ident "mdata" in (ident,CVar ident)+        (loId,loE) = let ident = Ident "lo" in (ident,CVar ident)+        (hiId,hiE) = let ident = Ident "hi" in (ident,CVar ident)+        value      = (loE .+. ((r ./. rMax) .*. (hiE .-. loE)))+        comment = fmap CComment+          ["uniform :: real -> real -> *(mdata real) -> ()"+          ,"------------------------------------------------"]+        assW       = CExpr . Just $ mdataPtrWeight mE .=. (floatE 0)+        assS       = CExpr . Just $ mdataPtrSample mE .=. value+        funcId     = Ident "uniform"+++uniformCG :: CExpr -> CExpr -> (CExpr -> CodeGen ())+uniformCG aE bE =+  \loc -> do+    reserveName "uniform"+    extDeclare . CFunDefExt $ uniformFun+    putExprStat $ CCall (CVar . Ident $ "uniform") [aE,bE,loc]+++{-+  This is very cryptic, but I assure you it is only building an AST for the+  Marsaglia Polar Method+-}++normalFun :: CFunDef+normalFun = CFunDef [CTypeSpec CVoid]+                    (CDeclr Nothing [CDDeclrIdent (Ident "normal")])+                    [typeDeclaration SReal aId+                    ,typeDeclaration SProb bId+                    ,typePtrDeclaration (SMeasure SReal) mId]+                    (CCompound $ comment ++ decls ++ stmts)++  where r      = CCast doubleDecl rand+        rMax   = CCast doubleDecl (CVar . Ident $ "RAND_MAX")+        (aId,aE) = let ident = Ident "a" in (ident,CVar ident)+        (bId,bE) = let ident = Ident "b" in (ident,CVar ident)+        (qId,qE) = let ident = Ident "q" in (ident,CVar ident)+        (uId,uE) = let ident = Ident "u" in (ident,CVar ident)+        (vId,vE) = let ident = Ident "v" in (ident,CVar ident)+        (rId,rE) = let ident = Ident "r" in (ident,CVar ident)+        (mId,mE) = let ident = Ident "mdata" in (ident,CVar ident)+        draw xE = CExpr . Just $ xE .=. (((r ./. rMax) .*. (floatE 2)) .-. (floatE 1))+        body = seqCStat [draw uE+                        ,draw vE+                        ,CExpr . Just $ qE .=. ((uE .*. uE) .+. (vE .*. vE))]+        polar = CWhile (qE .>. (floatE 1)) body True+        setR  = CExpr . Just $ rE .=. (sqrt (((CUnary CMinOp (floatE 2)) .*. log qE) ./. qE))+        finalValue = aE .+. (uE .*. rE .*. bE)+        comment = fmap (CBlockStat . CComment)+          ["normal :: real -> real -> *(mdata real) -> ()"+          ,"Marsaglia Polar Method"+          ,"-----------------------------------------------"]+        decls = fmap (CBlockDecl . typeDeclaration SReal) [uId,vId,qId,rId]+        stmts = fmap CBlockStat [polar,setR, assW, assS,CReturn Nothing]+        assW = CExpr . Just $ mdataPtrWeight mE .=. (floatE 0)+        assS = CExpr . Just $ mdataPtrSample mE .=. finalValue+++normalCG :: CExpr -> CExpr -> (CExpr -> CodeGen ())+normalCG aE bE =+  \loc -> do+    reserveName "normal"+    extDeclare . CFunDefExt $ normalFun+    putExprStat $ CCall (CVar . Ident $ "normal") [aE,bE,loc]++{-+  This method is from Marsaglia and Tsang "a simple method for generating gamma variables"+-}+gammaFun :: CFunDef+gammaFun = CFunDef [CTypeSpec CVoid]+                   (CDeclr Nothing [CDDeclrIdent (Ident "gamma")])+                   [typeDeclaration SProb aId+                   ,typeDeclaration SProb bId+                   ,typePtrDeclaration (SMeasure SProb) mId]+                   (CCompound $ comment ++ decls ++ stmts)+  where (aId,aE) = let ident = Ident "a" in (ident,CVar ident)+        (bId,bE) = let ident = Ident "b" in (ident,CVar ident)+        (cId,cE) = let ident = Ident "c" in (ident,CVar ident)+        (dId,dE) = let ident = Ident "d" in (ident,CVar ident)+        (xId,xE) = let ident = Ident "x" in (ident,CVar ident)+        (vId,vE) = let ident = Ident "v" in (ident,CVar ident)+        (uId,uE) = let ident = Ident "u" in (ident,CVar ident)+        (mId,mE) = let ident = Ident "mdata" in (ident,CVar ident)+        comment = fmap (CBlockStat . CComment)+          ["gamma :: real -> prob -> *(mdata prob) -> ()"+          ,"Marsaglia and Tsang 'a simple method for generating gamma variables'"+          ,"--------------------------------------------------------------------"]+        decls = fmap CBlockDecl $ (fmap (typeDeclaration SReal) [dId,cId,vId])+                               ++ (fmap (typeDeclaration (SMeasure SReal)) [uId,xId])+        stmts = fmap CBlockStat $ [assD,assC,outerWhile]+        xS = mdataSample xE+        uS = mdataSample uE+        assD = CExpr . Just $ dE .=. (aE .-. ((floatE 1) ./. (floatE 3)))+        assC = CExpr . Just $ cE .=. ((floatE 1) ./. (sqrt ((floatE 9) .*. dE)))+        outerWhile = CWhile (intE 1) (seqCStat [innerWhile,assV,assU,exit]) False+        innerWhile = CWhile (vE .<=. (floatE 0)) (seqCStat [assX,assVIn]) True+        assX = CExpr . Just $ CCall (CVar . Ident $ "normal") [(floatE 0),(floatE 1),address xE]+        assVIn = CExpr . Just $ vE .=. ((floatE 1) .+. (cE .*. xS))+        assV = CExpr . Just $ vE .=. (vE .*. vE .*. vE)+        assU = CExpr . Just $ CCall (CVar . Ident $ "uniform") [(floatE 0),(floatE 1),address uE]+        exitC1 = uS .<. ((floatE 1) .-. ((floatE 0.331 .*. (xS .*. xS) .*. (xS .*. xS))))+        exitC2 = (log uS) .<. (((floatE 0.5) .*. (xS .*. xS)) .+. (dE .*. ((floatE 1.0) .-. vE .+. (log vE))))+        assW = CExpr . Just $ mdataPtrWeight mE .=. (floatE 0)+        assS = CExpr . Just $ mdataPtrSample mE .=. (log (dE .*. vE)) .+. bE+        exit = CIf (exitC1 .||. exitC2) (seqCStat [assW,assS,CReturn Nothing]) Nothing+++gammaCG :: CExpr -> CExpr -> (CExpr -> CodeGen ())+gammaCG aE bE =+  \loc -> do+     extDeclare $ mdataStruct SReal+     mapM_ reserveName ["uniform","normal","gamma"]+     mapM_ (extDeclare . CFunDefExt) [uniformFun,normalFun,gammaFun]+     putExprStat $ CCall (CVar . Ident $ "gamma") [aE,bE,loc]+++flattenMeasureOp+  :: forall abt typs args a .+     ( ABT Term abt+     , typs ~ UnLCs args+     , args ~ LCs typs )+  => MeasureOp typs a+  -> SArgs abt args+  -> (CExpr -> CodeGen ())+++flattenMeasureOp Uniform =+  \(a :* b :* End) ->+    \loc ->+      do (aId:bId:[]) <- replicateM 2 genIdent+         let aE = CVar aId+             bE = CVar bId+         declare SReal aId+         declare SReal bId+         flattenABT a aE+         flattenABT b bE+         uniformCG aE bE loc+++flattenMeasureOp Normal  =+  \(a :* b :* End) ->+    \loc ->+      do (aId:bId:[]) <- replicateM 2 genIdent+         let aE = CVar aId+             bE = CVar bId+         declare SReal aId+         declare SReal bId+         flattenABT a aE+         flattenABT b bE+         normalCG aE (exp bE) loc+++flattenMeasureOp Gamma =+  \(a :* b :* End) ->+    \loc ->+      do (aId:bId:[]) <- replicateM 2 genIdent+         let aE = CVar aId+             bE = CVar bId+         declare SReal aId+         declare SReal bId+         flattenABT a aE+         flattenABT b bE+         gammaCG (exp aE) bE loc+++flattenMeasureOp Beta =+  \(a :* b :* End) -> flattenABT (HKP.beta'' a b)+++flattenMeasureOp Categorical = \(arr :* End) ->+  \loc ->+    do arrId <- genIdent+       declare (typeOf arr) arrId+       let arrE = CVar arrId+       flattenABT arr arrE++       itId <- genIdent' "it"+       declare SInt itId+       let itE = CVar itId++       wSumId <- genIdent' "ws"+       declare SProb wSumId+       let wSumE = CVar wSumId+       assign wSumId (log (intE 0))++       let currE = indirect (arrayData arrE .+. itE)+           cond  = itE .<. (arraySize arrE)+           inc   = CUnary CPostIncOp itE++       isPar <- isParallel+       mkSequential++       -- first calculate the max weight+       forCG (itE .=. (intE 0)) cond inc $+         logSumExpCG (S.fromList [wSumE,currE]) wSumE++       -- draw number from uniform(0, weightSum)+       rId <- genIdent' "r"+       declare SReal rId+       let r    = CCast doubleDecl rand+           rMax = CCast doubleDecl (CVar . Ident $ "RAND_MAX")+           rE = CVar rId+       assign rId ((r ./. rMax) .*. (exp wSumE))++       assign wSumId (log (intE 0))+       assign itId (intE 0)+       whileCG (intE 1)+         $ do stat <- runCodeGenBlock $+                        do putExprStat $ mdataPtrWeight loc .=. (intE 0)+                           putExprStat $ mdataPtrSample loc .=. itE+                           putStat CBreak+              putStat $ CIf (rE .<. (exp wSumE)) stat Nothing+              logSumExpCG (S.fromList [wSumE,currE]) wSumE+              putExprStat $ CUnary CPostIncOp itE++       when isPar mkParallel+++flattenMeasureOp x = error $ "TODO: flattenMeasureOp: " ++ show x++---------------+-- Superpose --+---------------++flattenSuperpose+    :: (ABT Term abt)+    => NE.NonEmpty (abt '[] 'HProb, abt '[] ('HMeasure a))+    -> (CExpr -> CodeGen ())++-- do we need to normalize?+flattenSuperpose pairs =+  let pairs' = NE.toList pairs in++  if length pairs' == 1+  then \loc -> let (w,m) = head pairs' in+         do mId <- genIdent+            wId <- genIdent+            declare (typeOf m) mId+            declare SProb wId+            let mE = address . CVar $ mId+                wE = CVar wId+            flattenABT w wE+            flattenABT m mE+            putExprStat $ mdataPtrWeight loc .=. ((mdataPtrWeight mE) .+. wE)+            putExprStat $ mdataPtrSample loc .=. (mdataPtrSample mE)++  else \loc ->+         do wEs <- forM pairs' $ \(w,_) ->+                     do wId <- genIdent' "w"+                        declare SProb wId+                        let wE = CVar wId+                        flattenABT w wE+                        return wE++            wSumId <- genIdent' "ws"+            declare SProb wSumId+            let wSumE = CVar wSumId+            logSumExpCG (S.fromList wEs) wSumE++            -- draw number from uniform(0, weightSum)+            rId <- genIdent' "r"+            declare SReal rId+            let r    = CCast doubleDecl rand+                rMax = CCast doubleDecl (CVar . Ident $ "RAND_MAX")+                rE = CVar rId+            assign rId ((r ./. rMax) .*. (exp wSumE))++            -- an iterator for picking a measure+            itId <- genIdent' "it"+            declare SProb itId+            let itE = CVar itId+            assign itId (log (intE 0))++            -- an output measure to assign to+            outId <- genIdent' "out"+            declare (typeOf . snd . head $ pairs') outId+            let outE = address $ CVar outId++            outLabel <- genIdent' "exit"++            forM_ (zip wEs pairs')+              $ \(wE,(_,m)) ->+                  do logSumExpCG (S.fromList [itE,wE]) itE+                     stat <- runCodeGenBlock (flattenABT m outE >> putStat (CGoto outLabel))+                     putStat $ CIf (rE .<. (exp itE)) stat Nothing++            putStat $ CLabel outLabel (CExpr Nothing)+            putExprStat $ mdataPtrWeight loc .=. ((mdataPtrWeight outE) .+. wSumE)+            putExprStat $ mdataPtrSample loc .=. (mdataPtrSample outE)
+ haskell/Language/Hakaru/CodeGen/Pretty.hs view
@@ -0,0 +1,295 @@+--------------------------------------------------------------------------------+--                                                                  2016.09.08+-- |+-- Module      :  Language.Hakaru.CodeGen.Pretty+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  zsulliva@indiana.edu+-- Stability   :  experimental+-- Portability :  GHC-only+--+--   A pretty printer for the CodeGen AST+--+--------------------------------------------------------------------------------++module Language.Hakaru.CodeGen.Pretty+  ( pretty+  , prettyPrint+  , Pretty+  ) where++import Text.PrettyPrint+import Language.Hakaru.CodeGen.AST++prettyPrint :: Pretty a => a -> String+prettyPrint = render . pretty++class Pretty a where+  pretty :: a -> Doc+  prettyPrec :: Int -> a -> Doc++  pretty = prettyPrec 0+  prettyPrec _ = pretty++mpretty :: Pretty a => Maybe a -> Doc+mpretty Nothing  = empty+mpretty (Just x) = pretty x++mPrettyPrec :: Pretty a => Int -> Maybe a -> Doc+mPrettyPrec _ Nothing  = empty+mPrettyPrec p (Just x) = prettyPrec p x++-- will compare two precs and put parens if the prec is lower+parensPrec :: Int -> Int -> Doc -> Doc+parensPrec x y = if x <= y then parens else id++newline :: Doc+newline = char '\n'++--------------------------------------------------------------------------------+--                                  Top Level                                 --+--------------------------------------------------------------------------------++instance Pretty Ident where+  pretty (Ident i) = text i++instance Pretty CAST where+  pretty (CAST extdecls) = (vcat . fmap pretty $ extdecls) $$ newline++instance Pretty CExtDecl where+  pretty (CDeclExt d) =  newline <> pretty d <> semi+  pretty (CFunDefExt f) = newline <> pretty f+  pretty (CCommentExt s) = text "/*" <+> text s <+> text "*/"+  pretty (CPPExt p) = pretty p++instance Pretty CFunDef where+  pretty (CFunDef dspecs dr ds s) =+    ((hsep . fmap pretty $ dspecs)+     <+> pretty dr+     <>  (parens . hsep . punctuate comma . fmap pretty $ ds))+    $+$ pretty s++--------------------------------------------------------------------------------+--                               Preprocessor                                 --+--------------------------------------------------------------------------------++instance Pretty Preprocessor where+  pretty (PPDefine n x) = hsep . fmap text $ ["#define",n,x]+  pretty (PPInclude s) = text "#include" <+> text "<" <> text s <> text ">"+  pretty (PPUndef s) = text "#undef" <+> text s+  pretty (PPIf s) = text "#if" <+> text s+  pretty (PPIfDef s) = text "#ifdef" <+> text s+  pretty (PPIfNDef s) = text "#ifndef" <+> text s+  pretty (PPElse s) = text "#else" <+> text s+  pretty (PPElif s) = text "#elif" <+> text s+  pretty (PPEndif s) = text "#endif" <+> text s+  pretty (PPError s) = text "#error" <+> text s+  pretty (PPPragma ts) = space $$ text "#pragma" <+> (hsep . fmap text $ ts)+++--------------------------------------------------------------------------------+--                             CDeclarations                                  --+--------------------------------------------------------------------------------++instance Pretty CDecl where+  pretty (CDecl ds ps) =+    hsep [ hsep . fmap pretty $ ds+         , hsep . punctuate comma . fmap declarators $ ps]+    where declarators (dr, Nothing) = pretty dr+          declarators (dr, Just ilist) = pretty dr <+> text "=" <+> pretty ilist++instance Pretty CDeclr where+  pretty (CDeclr mp dds) =+    mpretty mp <+> (hsep . fmap pretty $ dds)++instance Pretty CPtrDeclr where+  pretty (CPtrDeclr ts) = text "*" <+> (hsep . fmap pretty $ ts)++instance Pretty CDirectDeclr where+  pretty (CDDeclrIdent i) = pretty i+  pretty (CDDeclrArr dd e) = pretty dd <+> (brackets . pretty $ e)+  pretty (CDDeclrFun dd ts) =+    pretty dd <+> (hsep . punctuate comma . fmap pretty $ ts)+++instance Pretty CDeclSpec where+  pretty (CStorageSpec ss) = pretty ss+  pretty (CTypeSpec ts) = pretty ts+  pretty (CTypeQual tq) = pretty tq+  pretty (CFunSpec _ ) = text "inline"  -- inline is the only CFunSpec++instance Pretty CStorageSpec where+  pretty CTypeDef = text "typedef"+  pretty CExtern = text "extern"+  pretty CStatic = text "static"+  pretty CAuto = text "auto"+  pretty CRegister = text "register"++instance Pretty CTypeQual where+  pretty CConstQual = text "const"+  pretty CVolatQual = text "volatile"++instance Pretty CTypeSpec where+  pretty CVoid = text "void"+  pretty CChar = text "char"+  pretty CShort = text "short"+  pretty CInt = text "int"+  pretty CLong = text "long"+  pretty CFloat = text "float"+  pretty CDouble = text "double"+  pretty CSigned = text "signed"+  pretty CUnsigned = text "unsigned"+  pretty (CSUType cs) = pretty cs+  pretty (CTypeDefType _) = error "TODO: Pretty TypeDef"+  pretty (CEnumType _) = error "TODO: Pretty EnumType"++instance Pretty CSUSpec where+  pretty (CSUSpec tag mi []) =+    pretty tag <+> mpretty mi+  pretty (CSUSpec tag mi ds) =+    (pretty tag <+> mpretty mi <+> lbrace)+    $+$ (nest (-1) $ (nest 2 . sep . fmap (\d -> pretty d <> semi)  $ ds)+                     $+$ rbrace)++instance Pretty CSUTag where+  pretty CStructTag = text "struct"+  pretty CUnionTag = text "union"++instance Pretty CEnum where+  pretty (CEnum _ _) = error "TODO: Pretty Enum"++instance Pretty CInit where+  pretty (CInitExpr _) = error "TODO: Pretty Init"+  pretty (CInitList _) = error "TODO: Pretty Init list"++instance Pretty CPartDesig where+  pretty (CArrDesig _) = error "TODO: Pretty Arr Desig"+  pretty (CMemberDesig _) = error "TODO: Pretty Memdesig"+++--------------------------------------------------------------------------------+--                                CStatements                                 --+--------------------------------------------------------------------------------++instance Pretty CStat where+  pretty (CLabel lId s) = pretty lId <> colon $$ nest 2 (pretty s)+  pretty (CGoto lId) = text "goto" <+> pretty lId <> semi+  pretty (CSwitch e s) = text "switch" <+> pretty e <+> (parens . pretty $ s )+  pretty (CCase e s) = text "case" <+> pretty e <> colon $$ nest 2 (pretty s)+  pretty (CDefault s) = text "default" <> colon $$ nest 2 (pretty s)+  pretty (CExpr me) = mpretty me <> semi+  pretty (CCompound bs) =+    nest (-1) (lbrace $+$ (nest 2 . vcat . fmap pretty $ bs) $+$ rbrace)++  pretty (CIf ce thns (Just elss)) = nest 1 $+    text "if" <+> (parens . prettyPrec (-5) $ ce)+              $+$ (nest 1 $ pretty thns)+              $+$ text "else"+              $+$ (nest 1 $ pretty elss)+  pretty (CIf ce thns Nothing) =+    text "if" <+> (parens . prettyPrec (-5) $ ce) $+$ (nest 1 $ pretty thns)++  pretty (CWhile ce s b) =+    if b+    then text "do" <+> pretty s <+> text "while" <+> (parens $ pretty ce) <> semi+    else text "while" <+> (parens $ pretty ce) $$ (nest 1 $ pretty s)++  pretty (CFor me mce mie s) =+    text "for"+    <+> (parens . hsep . punctuate semi . fmap (mPrettyPrec 10) $ [me,mce,mie])+    $$  (nest 1 $ pretty s)++  pretty CCont = text "continue" <> semi+  pretty CBreak = text "break" <> semi+  pretty (CReturn me) = text "return" <+> mpretty me  <> semi+  pretty (CComment s) = text "/*" <+> text s <+> text "*/"+  pretty (CPPStat p) = pretty p++instance Pretty CCompoundBlockItem where+  pretty (CBlockStat s) = pretty s+  pretty (CBlockDecl d) = pretty d <> semi+++--------------------------------------------------------------------------------+--                                CExpressions                                --+--------------------------------------------------------------------------------++instance Pretty CExpr where+  prettyPrec _ (CComma es) = hsep . punctuate comma . fmap pretty $ es+  prettyPrec _ (CAssign op le re) = pretty le <+> pretty op <+> pretty re+  prettyPrec _ (CCond ce thn els) = pretty ce <+> text "?" <+> pretty thn <+> colon <+> pretty els+  prettyPrec p (CBinary op e1 e2) =+    parensPrec p 0 . hsep $ [pretty e1, pretty op, pretty e2]+  prettyPrec p (CCast d e) =+    parensPrec p (2) $ parens (pretty d) <> pretty e+  prettyPrec p (CUnary op e) =+    if elem op [CPostIncOp,CPostDecOp]+    then parensPrec p (-1) $ prettyPrec (-1) e <> pretty op+    else parens $ pretty op <> prettyPrec (-1) e++  prettyPrec _ (CSizeOfExpr e) = text "sizeof" <> (parens . pretty $ e)+  prettyPrec _ (CSizeOfType d) = text "sizeof" <> (parens . pretty $ d)+  prettyPrec _ (CIndex arrId ie) = pretty arrId <> (brackets . pretty $ ie)+  prettyPrec _ (CCall fune es) =+    pretty fune <> (parens . hcat . punctuate comma . fmap pretty $ es)+  prettyPrec _ (CMember ve memId isPtr) =+    let op = text $ if isPtr then "." else "->"+    in  pretty ve <> op <> pretty memId+  prettyPrec _ (CVar varId) = pretty varId+  prettyPrec _ (CConstant c) = pretty c+  prettyPrec _ (CCompoundLit d ini) = parens (pretty d) <> pretty ini+++instance Pretty CAssignOp where+  pretty CAssignOp = text "="+  pretty CMulAssOp = text "*="+  pretty CDivAssOp = text "/="+  pretty CRmdAssOp = text "%="+  pretty CAddAssOp = text "+="+  pretty CSubAssOp = text "-="+  pretty CShlAssOp = text "<<="+  pretty CShrAssOp = text ">>="+  pretty CAndAssOp = text "&="+  pretty CXorAssOp = text "^="+  pretty COrAssOp  = text "|="+++instance Pretty CBinaryOp where+  pretty CMulOp = text "*"+  pretty CDivOp = text "/"+  pretty CRmdOp = text "%"+  pretty CAddOp = text "+"+  pretty CSubOp = text "-"+  pretty CShlOp = text "<<"+  pretty CShrOp = text ">>"+  pretty CLeOp  = text "<"+  pretty CGrOp  = text ">"+  pretty CLeqOp = text "<="+  pretty CGeqOp = text ">="+  pretty CEqOp  = text "=="+  pretty CNeqOp = text "!="+  pretty CAndOp = text "&"+  pretty CXorOp = text "^"+  pretty COrOp  = text "|"+  pretty CLndOp = text "&&"+  pretty CLorOp = text "||"+++instance Pretty CUnaryOp where+  pretty CPreIncOp  = text "++"+  pretty CPreDecOp  = text "--"+  pretty CPostIncOp = text "++"+  pretty CPostDecOp = text "--"+  pretty CAdrOp     = text "&"+  pretty CIndOp     = text "*"+  pretty CPlusOp    = text "+"+  pretty CMinOp     = text "-"+  pretty CCompOp    = text "~"+  pretty CNegOp     = text "!"+++instance Pretty CConst where+  pretty (CIntConst i)    = text . show $ i+  pretty (CCharConst c)   = char c+  pretty (CFloatConst f)  = float f+  pretty (CStringConst s) = text . show $ s
+ haskell/Language/Hakaru/CodeGen/Types.hs view
@@ -0,0 +1,349 @@+{-# LANGUAGE DataKinds,+             FlexibleContexts,+             GADTs,+             KindSignatures #-}++----------------------------------------------------------------+--                                                    2016.07.11+-- |+-- Module      :  Language.Hakaru.CodeGen.Types+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  zsulliva@indiana.edu+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- Provides tools for building C Types from Hakaru types+--+----------------------------------------------------------------++module Language.Hakaru.CodeGen.Types+  ( buildDeclaration+  , buildPtrDeclaration++  -- tools for building C types+  , typeDeclaration+  , typePtrDeclaration++  -- arrays+  , arrayDeclaration+  , arrayName+  , arrayStruct+  , arraySize+  , arrayData+  , arrayPtrSize+  , arrayPtrData++  -- mdata+  , mdataDeclaration+  , mdataPtrDeclaration+  , mdataName+  , mdataStruct+  , mdataStruct'+  , mdataWeight+  , mdataSample+  , mdataPtrWeight+  , mdataPtrSample++  , datumDeclaration+  , datumName+  , datumStruct+  , functionDef+  , datumSum+  , datumProd++  , buildType+  , mkDecl+  , mkPtrDecl+  , buildStruct+  , buildUnion++  , intDecl+  , natDecl+  , doubleDecl+  , doublePtr+  , intPtr+  , natPtr+  , boolTyp+  , binaryOp+  ) where++import Control.Monad.State++import Language.Hakaru.Syntax.AST+import Language.Hakaru.Types.DataKind+import Language.Hakaru.Types.HClasses+import Language.Hakaru.Types.Sing+import Language.Hakaru.CodeGen.AST++import Prelude hiding (exp,log,sqrt)++buildDeclaration :: CTypeSpec -> Ident -> CDecl+buildDeclaration ctyp ident =+  CDecl [ CTypeSpec ctyp ]+        [( CDeclr Nothing [ CDDeclrIdent ident ]+         , Nothing)]++buildPtrDeclaration :: CTypeSpec -> Ident -> CDecl+buildPtrDeclaration ctyp ident =+  CDecl [ CTypeSpec ctyp ]+        [( CDeclr (Just $ CPtrDeclr []) [ CDDeclrIdent ident ]+         , Nothing)]++typeDeclaration :: Sing (a :: Hakaru) -> Ident -> CDecl+typeDeclaration typ ident =+  CDecl (fmap CTypeSpec $ buildType typ)+        [( CDeclr Nothing [ CDDeclrIdent ident ]+         , Nothing)]++typePtrDeclaration :: Sing (a :: Hakaru) -> Ident -> CDecl+typePtrDeclaration typ ident =+  CDecl (fmap CTypeSpec $ buildType typ)+        [( CDeclr (Just $ CPtrDeclr [])+                  [ CDDeclrIdent ident ]+         , Nothing)]++--------------------------------------------------------------------------------+-- Representing Hakaru Arrays++arrayName :: Sing (a :: Hakaru) -> String+arrayName SInt  = "arrayInt"+arrayName SNat  = "arrayNat"+arrayName SReal = "arrayReal"+arrayName SProb = "arrayProb"+arrayName t    = error $ "arrayName: cannot make array from type: " ++ show t++arrayStruct :: Sing (a :: Hakaru) -> CExtDecl+arrayStruct t = CDeclExt (CDecl [CTypeSpec $ arrayStruct' t] [])++arrayStruct' :: Sing (a :: Hakaru) -> CTypeSpec+arrayStruct' t = aStruct+  where aSize   = buildDeclaration CInt (Ident "size")+        aData   = typePtrDeclaration t (Ident "data")+        aStruct = buildStruct (Just . Ident . arrayName $ t) [aSize,aData]+++arrayDeclaration+  :: Sing (a :: Hakaru)+  -> Ident+  -> CDecl+arrayDeclaration typ = buildDeclaration (callStruct (arrayName typ))+++arraySize :: CExpr -> CExpr+arraySize e = CMember e (Ident "size") True++arrayData :: CExpr -> CExpr+arrayData e = CMember e (Ident "data") True++arrayPtrSize :: CExpr -> CExpr+arrayPtrSize e = CMember e (Ident "size") False++arrayPtrData :: CExpr -> CExpr+arrayPtrData e = CMember e (Ident "data") False++--------------------------------------------------------------------------------+-- Measure Data++mdataName :: Sing (a :: Hakaru) -> String+mdataName SInt  = "mdataInt"+mdataName SNat  = "mdataNat"+mdataName SReal = "mdataReal"+mdataName SProb = "mdataProb"+mdataName (SArray SInt)  = "mdataArrayInt"+mdataName (SArray SNat)  = "mdataArrayNat"+mdataName (SArray SReal) = "mdataArrayReal"+mdataName (SArray SProb) = "mdataArrayProb"+mdataName t    = error $ "mdataName: cannot make mdata from type: " ++ show t++mdataStruct :: Sing (a :: Hakaru) -> CExtDecl+mdataStruct t = CDeclExt (CDecl [CTypeSpec $ mdataStruct' t] [])++mdataStruct' :: Sing (a :: Hakaru) -> CTypeSpec+mdataStruct' t = mdStruct+  where weight = buildDeclaration CDouble (Ident "weight")+        sample = typeDeclaration t (Ident "sample")+        mdStruct = buildStruct (Just . Ident . mdataName $ t) [weight,sample]++mdataDeclaration+  :: Sing (a :: Hakaru)+  -> Ident+  -> CDecl+mdataDeclaration typ = buildDeclaration (callStruct (mdataName typ))++mdataPtrDeclaration+  :: Sing (a :: Hakaru)+  -> Ident+  -> CDecl+mdataPtrDeclaration typ = buildPtrDeclaration (callStruct (mdataName typ))++mdataWeight :: CExpr -> CExpr+mdataWeight d = CMember d (Ident "weight") True++mdataSample :: CExpr -> CExpr+mdataSample d = CMember d (Ident "sample") True++mdataPtrWeight :: CExpr -> CExpr+mdataPtrWeight d = CMember d (Ident "weight") False++mdataPtrSample :: CExpr -> CExpr+mdataPtrSample d = CMember d (Ident "sample") False++--------------------------------------------------------------------------------+-- | datumProd and datumSum use a store of names, which needs to match up with+-- the names used when they are assigned and printed+-- datumDeclaration declares struct internally+-- datumStruct declares struct definitions externally++-- | datumName provides a unique name to identify a struct type+datumName :: Sing (a :: [[HakaruFun]]) -> String+datumName SVoid = "V"+datumName (SPlus prodD sumD) = concat ["S",datumName' prodD,datumName sumD]+  where datumName' :: Sing (a :: [HakaruFun]) -> String+        datumName' SDone = "U"+        datumName' (SEt (SKonst x) prod') = concat ["S",tail . show $ x,datumName' prod']+        datumName' (SEt SIdent _)         = error "TODO: datumName of SIdent"++datumNames :: [String]+datumNames = filter (\n -> not $ elem (head n) ['0'..'9']) names+  where base = ['0'..'9'] ++ ['a'..'z']+        names = [[x] | x <- base] `mplus` (do n <- names+                                              [n++[x] | x <- base])++datumStruct :: (Sing (HData' t)) -> CExtDecl+datumStruct (SData _ typ) = CDeclExt $ datumSum typ (Ident (datumName typ))++datumDeclaration+  :: (Sing (HData' t))+  -> Ident+  -> CDecl+datumDeclaration (SData _ typ) = buildDeclaration (callStruct (datumName typ))++datumSum :: Sing (a :: [[HakaruFun]]) -> Ident -> CDecl+datumSum funs ident =+  let declrs = fst $ runState (datumSum' funs) datumNames+      union  = buildDeclaration (buildUnion declrs) (Ident "sum")+      index  = buildDeclaration CInt (Ident "index")+      struct = buildStruct (Just ident) $ case declrs of+                                            [] -> [index]+                                            _  -> [index,union]+  in CDecl [ CTypeSpec struct ] []++datumSum' :: Sing (a :: [[HakaruFun]]) -> State [String] [CDecl]+datumSum' SVoid          = return []+datumSum' (SPlus prod rest) =+  do (name:names) <- get+     put names+     let ident = Ident name+         mdecl = datumProd prod ident+     rest' <- datumSum' rest+     case mdecl of+       Nothing -> return rest'+       Just d  -> return $ [d] ++ rest'+++datumProd :: Sing (a :: [HakaruFun]) -> Ident -> Maybe CDecl+datumProd SDone _     = Nothing+datumProd funs ident  =+  let declrs = fst $ runState (datumProd' funs) datumNames+  in  Just $ buildDeclaration (buildStruct Nothing $ declrs) ident++-- datumProd uses a store of names, which needs to match up with the names used+-- when they are assigned as well as printed+datumProd' :: Sing (a :: [HakaruFun]) -> State [String] [CDecl]+datumProd' SDone                 = return []+datumProd' (SEt (SKonst t) rest) =+  do (name:names) <- get+     put names+     let ident = Ident name+         decl  = typeDeclaration t ident+     rest' <- datumProd' rest+     return $ [decl] ++ rest'+datumProd' (SEt SIdent _) = error "TODO: datumProd' SIdent"++----------------------------------------------------------------++functionDef+  :: Sing (a :: Hakaru)+  -> Ident+  -> [CDecl]+  -> [CDecl]+  -> [CStat]+  -> CFunDef+functionDef typ ident argDecls internalDecls stmts =+  CFunDef (fmap CTypeSpec $ buildType typ)+          (CDeclr Nothing [ CDDeclrIdent ident ])+          argDecls+          (CCompound ((fmap CBlockDecl internalDecls) ++ (fmap CBlockStat stmts)))++----------------------------------------------------------------+-- | buildType function do the work of describing how the Hakaru+-- type will be stored in memory. Arrays needed their own+-- declaration function for their arity+buildType :: Sing (a :: Hakaru) -> [CTypeSpec]+buildType SInt         = [CInt]+buildType SNat         = [CUnsigned, CInt]+buildType SProb        = [CDouble]+buildType SReal        = [CDouble]+buildType (SMeasure x) = [callStruct . mdataName $ x]+buildType (SArray t)   = [callStruct $ arrayName t]+buildType (SFun _ x)   = buildType $ x -- build type the function returns+buildType (SData _ t)  = [callStruct $ datumName t]+++-- these mk...Decl functions are used in coersions+mkDecl :: [CTypeSpec] -> CDecl+mkDecl t = CDecl (fmap CTypeSpec t) []++mkPtrDecl :: [CTypeSpec] -> CDecl+mkPtrDecl t = CDecl (fmap CTypeSpec t)+                    [( CDeclr (Just $ CPtrDeclr []) []+                     , Nothing )]++buildStruct :: Maybe Ident -> [CDecl] -> CTypeSpec+buildStruct mi decls =+  CSUType (CSUSpec CStructTag mi decls)++-- | callStruct will give the type spec calling a struct we have already declared externally+callStruct :: String -> CTypeSpec+callStruct name =+  CSUType (CSUSpec CStructTag (Just (Ident name)) [])++buildUnion :: [CDecl] -> CTypeSpec+buildUnion decls =+ CSUType (CSUSpec CUnionTag Nothing decls)+++intDecl, natDecl, doubleDecl :: CDecl+intDecl    = mkDecl [CInt]+natDecl    = CDecl [CTypeSpec CUnsigned+                   ,CTypeSpec CInt]+                   [( CDeclr (Just $ CPtrDeclr []) [], Nothing )]+doubleDecl = mkDecl [CDouble]++intPtr, natPtr, doublePtr :: CDecl+intPtr    = mkPtrDecl [CInt]+natPtr    = CDecl [CTypeSpec CUnsigned, CTypeSpec CInt] []+doublePtr = mkPtrDecl [CDouble]++boolTyp :: CDecl+boolTyp =+  CDecl [CTypeSpec+          (CSUType+            (CSUSpec CStructTag+                     (Just (Ident "bool"))+                     [buildDeclaration CInt (Ident "index")]))]+        []++++binaryOp :: NaryOp a -> CExpr -> CExpr -> CExpr+binaryOp (Sum HSemiring_Prob)  a b = CBinary CAddOp (exp a) (exp b)+binaryOp (Prod HSemiring_Prob) a b = CBinary CAddOp a b+binaryOp (Sum _)               a b = CBinary CAddOp a b+binaryOp (Prod _)              a b = CBinary CMulOp a b+-- vvv Operations on bools, keeping in mind that in Hakaru-C: 0 is true and 1 is false+binaryOp And                   a b = CUnary CNegOp (CBinary CEqOp  a b) -- still wrong+binaryOp Or                    a b = CBinary CAndOp a b                 -- still wrong+binaryOp Xor                   a b = CBinary CLorOp a b                 -- still wrong+binaryOp x _ _ = error $ "TODO: binaryOp " ++ show x
+ haskell/Language/Hakaru/CodeGen/Wrapper.hs view
@@ -0,0 +1,349 @@+{-# LANGUAGE BangPatterns,+             CPP,+             OverloadedStrings,+             DataKinds,+             FlexibleContexts,+             GADTs,+             KindSignatures,+             RankNTypes,+             ScopedTypeVariables #-}++----------------------------------------------------------------+--                                                    2016.06.23+-- |+-- Module      :  Language.Hakaru.CodeGen.Wrapper+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  zsulliva@indiana.edu+-- Stability   :  experimental+-- Portability :  GHC-only+--+--   The purpose of the wrapper is to intelligently wrap CStatements+-- into CFunctions and CProgroms to be printed by 'hkc'+--+----------------------------------------------------------------+++module Language.Hakaru.CodeGen.Wrapper+  ( wrapProgram+  , PrintConfig(..)+  ) where++import           Language.Hakaru.Syntax.ABT+import           Language.Hakaru.Syntax.AST+import           Language.Hakaru.Syntax.IClasses+import           Language.Hakaru.Syntax.TypeCheck+import           Language.Hakaru.Syntax.TypeOf (typeOf)+import           Language.Hakaru.Types.Sing+import           Language.Hakaru.CodeGen.CodeGenMonad+import           Language.Hakaru.CodeGen.Flatten+import           Language.Hakaru.CodeGen.Types+import           Language.Hakaru.CodeGen.AST+import           Language.Hakaru.Types.DataKind (Hakaru(..))++import           Control.Monad.State.Strict+import           Prelude            as P hiding (unlines,exp)+++#if __GLASGOW_HASKELL__ < 710+import           Control.Applicative+#endif+++-- | wrapProgram is the top level C codegen. Depending on the type a program+--   will have a different construction. It will produce an effect in the+--   CodeGenMonad that will produce a standalone C file containing the CPP+--   includes, struct declarations, functions, and sometimes a main.+wrapProgram+  :: TypedAST (TrivialABT Term) -- ^ Some Hakaru ABT+  -> Maybe String               -- ^ Maybe an output name+  -> PrintConfig                -- ^ show weights?+  -> CodeGen ()+wrapProgram tast@(TypedAST typ _) mn pc =+  do sequence_ . fmap (extDeclare . CPPExt) . header $ typ+     baseCG+     return ()+  where baseCG = case (tast,mn) of+               ( TypedAST (SFun _ _) abt, Just name ) ->+                 do reserveName name+                    flattenTopLambda abt $ Ident name++               ( TypedAST (SFun _ _) abt, Nothing   ) ->+                 genIdent' "fn" >>= \name ->+                   flattenTopLambda abt name+++               ( TypedAST _ _,                  Just _ ) -> undefined+                 -- do reserveName name+                 --    defineFunction typ'+                 --                   (Ident name)+                 --                   []+                 --                   (putStat . CReturn . Just =<< flattenABT abt)++               ( TypedAST typ'       abt, Nothing   ) ->+                 mainFunction pc typ' abt++++header :: Sing (a :: Hakaru) -> [Preprocessor]+header (SMeasure _) = fmap PPInclude ["time.h", "stdlib.h", "stdio.h", "math.h"]+header _            = fmap PPInclude ["stdlib.h", "stdio.h", "math.h"]++++--------------------------------------------------------------------------------+--                             A Main Function                                --+--------------------------------------------------------------------------------+{-++Create standalone C program for a Hakaru ABT. This program will also print the+computed value to stdin.++-}++mainFunction+  :: ABT Term abt+  => PrintConfig+  -> Sing (a :: Hakaru)    -- ^ type of program+  -> abt '[] (a :: Hakaru) -- ^ Hakaru ABT+  -> CodeGen ()++-- when measure, compile to a sampler+mainFunction pc typ@(SMeasure t) abt =+  let ident   = Ident "measure"+      funId   = Ident "main"+      mdataId = Ident "mdata"+  in  do reserveName "measure"+         reserveName "mdata"+         reserveName "main"++         extDeclare . mdataStruct $ t++         -- defined a measure function that returns mdata+         funCG CVoid ident [mdataPtrDeclaration t mdataId] $+           do flattenABT abt (CVar mdataId)+              putStat (CReturn Nothing)++  --        -- need to set seed?+  --        -- srand(time(NULL));++         printf pc typ (CVar ident)+         putStat . CReturn . Just $ intE 0++         !cg <- get+         extDeclare . CFunDefExt $ functionDef SInt+                                               funId+                                               []+                                               (P.reverse $ declarations cg)+                                               (P.reverse $ statements cg)+  -- where isSArray (SArray _) = True+  --       isSArray _          = False+  --       mkArrayStruct :: Sing (a :: Hakaru) -> CExtDecl+  --       mkArrayStruct (SArray t) = arrayStruct t+  --       mkArrayStruct _          = error "Not Array"+  --       getArrayType :: Sing (b :: Hakaru) -> [CTypeSpec]+  --       getArrayType (SArray t) = case buildType t of+  --                                   [] -> error "wrapper: this shouldn't happen"+  --                                   t  -> t+  --       getArrayType _          = error "Not Array"+  --       getPlateArity :: ABT Term abt => Term abt a -> abt '[] 'HNat+  --       getPlateArity (Plate :$ arity :* _ :* End) = arity+  --       getPlateArity _ = error "mainFunction not a plate"++-- just a computation+mainFunction pc typ abt =+  let resId = Ident "result"+      resE  = CVar resId+      funId = Ident "main"+  in  do reserveName "result"+         reserveName "main"++         declare typ resId+         flattenABT abt resE++         printf pc typ resE+         putStat . CReturn . Just $ intE 0++         cg <- get+         extDeclare . CFunDefExt $ functionDef SInt+                                              funId+                                              []+                                              (P.reverse $ declarations cg)+                                              (P.reverse $ statements cg)+++--------------------------------------------------------------------------------+--                               Printing Values                              --+--------------------------------------------------------------------------------+{-++In HKC the printconfig is parsed from the command line. The default being that+we don't show weights and probabilities are printed as normal real values.++-}++data PrintConfig+  = PrintConfig { showWeights   :: Bool+                , showProbInLog :: Bool+                } deriving Show+++printf+  :: PrintConfig+  -> Sing (a :: Hakaru) -- ^ Hakaru type to be printed+  -> CExpr              -- ^ CExpr representing value+  -> CodeGen ()++printf pc mt@(SMeasure t) sampleFunc =+  case t of+    _ -> do mId <- genIdent' "m"+            declare mt mId+            let mE = CVar mId+                getSampleS   = CExpr . Just $ CCall sampleFunc [address mE]+                printSampleE = CExpr . Just+                             $ CCall (CVar . Ident $ "printf")+                                     $ [ stringE $ printfText pc mt "\n"]+                                     ++ (if showWeights pc+                                         then [ if showProbInLog pc+                                                then mdataWeight mE+                                                else exp $ mdataWeight mE ]+                                         else [])+                                     ++ [ case t of+                                            SProb -> if showProbInLog pc+                                                     then mdataSample mE+                                                     else exp $ mdataSample mE+                                            _ -> mdataSample mE ]+                wrapSampleFunc = CCompound $ [CBlockStat getSampleS+                                             ,CBlockStat $ CIf ((exp $ mdataWeight mE) .>. (floatE 0)) printSampleE Nothing]+            putStat $ CWhile (intE 1) wrapSampleFunc False+++printf pc (SArray t) arg =+  do iterId <- genIdent' "it"+     declare SInt iterId+     let iter   = CVar iterId+         result = arg+         dataPtr = CMember result (Ident "data") True+         sizeVar = CMember result (Ident "size") True+         cond     = iter .<. sizeVar+         inc      = CUnary CPostIncOp iter+         currInd  = indirect (dataPtr .+. iter)+         loopBody = putExprStat $ CCall (CVar . Ident $ "printf")+                                        [ stringE $ printfText pc t " "+                                        , currInd ]+++     putString "[ "+     mkSequential -- cant print arrays in parallel+     forCG (iter .=. (intE 0)) cond inc loopBody+     putString "]\n"+  where putString s = putExprStat $ CCall (CVar . Ident $ "printf")+                                          [stringE s]++printf pc SProb arg =+  putExprStat $ CCall (CVar . Ident $ "printf")+                      [ stringE $ printfText pc SProb "\n"+                      , if showProbInLog pc+                        then arg+                        else exp arg ]++printf pc typ arg =+  putExprStat $ CCall (CVar . Ident $ "printf")+                      [ stringE $ printfText pc typ "\n"+                      , arg ]++++printfText :: PrintConfig -> Sing (a :: Hakaru) -> (String -> String)+printfText _ SInt         = \s -> "%d" ++ s+printfText _ SNat         = \s -> "%d" ++ s+printfText c SProb        = \s -> if showProbInLog c+                                  then "exp(%.15f)" ++ s+                                  else "%.15f" ++ s+printfText _ SReal        = \s -> "%.17f" ++ s+printfText c (SMeasure t) = if showWeights c+                            then \s -> if showProbInLog c+                                       then "exp(%.15f) " ++ printfText c t s+                                       else "%.15f " ++ printfText c t s+                            else printfText c t+printfText c (SArray t)   = printfText c t+printfText _ (SFun _ _)   = id+printfText _ (SData _ _)  = \s -> "TODO: printft datum" ++ s+++--------------------------------------------------------------------------------+--                           Wrapping   Lambdas                               --+--------------------------------------------------------------------------------+{-++Lambdas become function in C. The Hakaru ABT only allows one arguement for each+lambda. So at the top level of a Hakaru program that is a function there may be+several nested lambdas. In C however, we can and should coalesce these into one+function with several arguements. This is what flattenTopLambda is for.++-}+++flattenTopLambda+  :: ABT Term abt+  => abt '[] a+  -> Ident+  -> CodeGen ()+flattenTopLambda abt name =+    coalesceLambda abt $ \vars abt' ->+    let varMs = foldMap11 (\v -> [mkVarDecl v =<< createIdent v]) vars+        typ   = typeOf abt'+    in  do argDecls <- sequence varMs+           cg <- get+           case typ of+             -- SMeasure _ -> error "flattenTopLambda: for Measures"+             -- SMeasure _ -> do let m       = putStat . CReturn . Just =<< flattenABT abt'+             --                      (_,cg') = runState m $ cg { statements = []+             --                                                , declarations = [] }+             --                  put $ cg' { statements   = statements cg+             --                            , declarations = declarations cg }+             --                  extDeclare . CFunDefExt+             --                    $ functionDef typ name+             --                                      argDecls+             --                                      (P.reverse $ declarations cg')+             --                                      (P.reverse $ statements cg')+             _ -> do let m       = do outId <- genIdent' "out"+                                      declare (typeOf abt') outId+                                      let outE = CVar outId+                                      flattenABT abt' outE+                                      putStat . CReturn . Just $ outE+                         (_,cg') = runState m $ cg { statements = []+                                                   , declarations = [] }+                     put $ cg' { statements   = statements cg+                               , declarations = declarations cg }+                     extDeclare . CFunDefExt+                       $ functionDef typ name+                                         argDecls+                                         (P.reverse $ declarations cg')+                                         (P.reverse $ statements cg')+  -- do at top level+  where coalesceLambda+          :: ABT Term abt+          => abt '[] a+          -> ( forall (ys :: [Hakaru]) b+             . List1 Variable ys -> abt '[] b -> r)+          -> r+        coalesceLambda abt_ k =+          caseVarSyn abt_ (const (k Nil1 abt_)) $ \term ->+            case term of+              (Lam_ :$ body :* End) ->+                caseBind body $ \v body' ->+                  coalesceLambda body' $ \vars body'' -> k (Cons1 v vars) body''+              _ -> k Nil1 abt_+++        mkVarDecl :: Variable (a :: Hakaru) -> Ident -> CodeGen CDecl+        mkVarDecl (Variable _ _ SInt)  = return . typeDeclaration SInt+        mkVarDecl (Variable _ _ SNat)  = return . typeDeclaration SNat+        mkVarDecl (Variable _ _ SProb) = return . typeDeclaration SProb+        mkVarDecl (Variable _ _ SReal) = return . typeDeclaration SReal+        mkVarDecl (Variable _ _ (SArray t)) = \i -> do extDeclare $ arrayStruct t+                                                       return $ arrayDeclaration t i+        mkVarDecl (Variable _ _ d@(SData _ _)) = \i -> do extDeclare $ datumStruct d+                                                          return $ datumDeclaration d i+        mkVarDecl v = error $ "flattenSCon.Lam_.mkVarDecl cannot handle vars of type " ++ show v
+ haskell/Language/Hakaru/Command.hs view
@@ -0,0 +1,34 @@+{-# LANGUAGE DataKinds #-}+module Language.Hakaru.Command where++import           Language.Hakaru.Syntax.ABT+import qualified Language.Hakaru.Syntax.AST as T+import           Language.Hakaru.Parser.Parser hiding (style)+import           Language.Hakaru.Parser.SymbolResolve (resolveAST)+import           Language.Hakaru.Syntax.TypeCheck++import qualified Data.Text    as Text+import qualified Data.Text.IO as IO+import           Data.Vector++type Term a = TrivialABT T.Term '[] a++parseAndInfer :: Text.Text+              -> Either Text.Text (TypedAST (TrivialABT T.Term))+parseAndInfer x =+    case parseHakaru x of+    Left  err  -> Left (Text.pack . show $ err)+    Right past ->+        let m = inferType (resolveAST past) in+        runTCM m (splitLines x) LaxMode++splitLines :: Text.Text -> Maybe (Vector Text.Text)+splitLines = Just . fromList . Text.lines++readFromFile :: String -> IO Text.Text+readFromFile "-" = IO.getContents+readFromFile x   = IO.readFile x++writeToFile :: String -> (Text.Text -> IO ())+writeToFile "-" = IO.putStrLn+writeToFile x   = IO.writeFile x
+ haskell/Language/Hakaru/Disintegrate.hs view
@@ -0,0 +1,1830 @@+{-# LANGUAGE CPP+           , GADTs+           , EmptyCase+           , KindSignatures+           , DataKinds+           , PolyKinds+           , TypeOperators+           , ScopedTypeVariables+           , Rank2Types+           , MultiParamTypeClasses+           , TypeSynonymInstances+           , FlexibleInstances+           , FlexibleContexts+           , UndecidableInstances+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.06.29+-- |+-- Module      :  Language.Hakaru.Disintegrate+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- Disintegration via lazy partial evaluation.+--+-- N.B., the forward direction of disintegration is /not/ just+-- partial evaluation! In the version discussed in the paper we+-- must also ensure that no heap-bound variables occur in the result,+-- which requires using HNFs rather than WHNFs. That condition is+-- sound, but a bit too strict; we could generalize this to handle+-- cases where there may be heap-bound variables remaining in neutral+-- terms, provided we (a) don't end up trying to go both forward+-- and backward on the same variable, and (more importantly) (b)+-- end up with the proper Jacobian. The paper version is rigged to+-- ensure that whenever we recurse into two subexpressions (e.g.,+-- the arguments to addition) one of them has a Jacobian of zero,+-- thus when going from @x*y@ to @dx*y + x*dy@ one of the terms+-- cancels out.+--+-- /Developer's Note:/ To help keep the code clean, we use the+-- worker\/wrapper transform. However, due to complexities in+-- typechecking GADTs, this often confuses GHC if you don't give+-- just the right type signature on definitions. This confusion+-- shows up whenever you get error messages about an \"ambiguous\"+-- choice of 'ABT' instance, or certain types of \"couldn't match+-- @a@ with @a1@\" error messages. To eliminate these issues we use+-- @-XScopedTypeVariables@. In particular, the @abt@ type variable+-- must be bound by the wrapper (i.e., the top-level definition),+-- and the workers should just refer to that same type variable+-- rather than quantifying over abother @abt@ type. In addition,+-- whatever other type variables there are (e.g., the @xs@ and @a@+-- of an @abt xs a@ argument) should be polymorphic in the workers+-- and should /not/ reuse the other analogous type variables bound+-- by the wrapper.+--+-- /Developer's Note:/ In general, we'd like to emit weights and+-- guards \"as early as possible\"; however, determining when that+-- actually is can be tricky. If we emit them way-too-early then+-- we'll get hygiene errors because bindings for the variables they+-- use have not yet been emitted. We can fix these hygiene erors+-- by calling 'atomize', to ensure that all the necessary bindings+-- have already been emitted. But that may still emit things too+-- early, because emitting th variable-binding statements now means+-- that we can't go forward\/backward on them later on; which may+-- cause us to bot unnecessarily. One way to avoid this bot issue+-- is to emit guards\/weights later than necessary, by actually+-- pushing them onto the context (and then emitting them whenever+-- we residualize the context). This guarantees we don't emit too+-- early; but the tradeoff is we may end up generating duplicate+-- code by emitting too late. One possible (currently unimplemented)+-- solution to that code duplication issue is to let these statements+-- be emitted too late, but then have a post-processing step to+-- lift guards\/weights up as high as they can go. To avoid problems+-- about testing programs\/expressions for equality, we can use a+-- hash-consing trick so we keep track of the identity of guard\/weight+-- statements, then we can simply compare those identities and only+-- after the lifting do we replace the identity hash with the actual+-- statement.+----------------------------------------------------------------+module Language.Hakaru.Disintegrate+    (+    -- * the Hakaru API+      disintegrateWithVar+    , disintegrate+    , densityWithVar+    , density+    , observe+    , determine+    +    -- * Implementation details+    , perform+    , atomize+    , constrainValue+    , constrainOutcome+    ) where++#if __GLASGOW_HASKELL__ < 710+import           Data.Functor         ((<$>))+import           Data.Foldable        (Foldable, foldMap)+import           Data.Traversable     (Traversable)+import           Control.Applicative  (Applicative(..))+#endif+import           Control.Applicative  (Alternative(..))+import           Control.Monad        ((<=<), guard)+import           Data.Functor.Compose (Compose(..))+import qualified Data.Traversable     as T+import           Data.List.NonEmpty   (NonEmpty(..))+import qualified Data.List.NonEmpty   as L+import qualified Data.Text            as Text+import qualified Data.IntMap          as IM+import           Data.Sequence        (Seq)+import qualified Data.Sequence        as S+import           Data.Proxy           (KProxy(..))+import qualified Data.Set             as Set (fromList)+import           Data.Maybe           (fromMaybe)++import Language.Hakaru.Syntax.IClasses+import Data.Number.Natural+import Language.Hakaru.Types.DataKind+import Language.Hakaru.Types.Sing+import qualified Language.Hakaru.Types.Coercion as C+import Language.Hakaru.Types.HClasses+import Language.Hakaru.Syntax.TypeOf+import Language.Hakaru.Syntax.AST+import Language.Hakaru.Syntax.Datum+import Language.Hakaru.Syntax.DatumCase (DatumEvaluator, MatchResult(..), matchBranches)+import Language.Hakaru.Syntax.ABT+import Language.Hakaru.Evaluation.Types+import Language.Hakaru.Evaluation.Lazy hiding (evaluate,update)+import Language.Hakaru.Evaluation.DisintegrationMonad+import qualified Language.Hakaru.Syntax.Prelude as P+import qualified Language.Hakaru.Expect         as E++#ifdef __TRACE_DISINTEGRATE__+import qualified Text.PrettyPrint     as PP+import Language.Hakaru.Pretty.Haskell+import Debug.Trace                    (trace, traceM)+#endif+++----------------------------------------------------------------++lam_ :: (ABT Term abt) => Variable a -> abt '[] b -> abt '[] (a ':-> b)+lam_ x e = syn (Lam_ :$ bind x e :* End)+++-- | Disintegrate a measure over pairs with respect to the lebesgue+-- measure on the first component. That is, for each measure kernel+-- @n <- disintegrate m@ we have that @m == bindx lebesgue n@. The+-- first two arguments give the hint and type of the lambda-bound+-- variable in the result. If you want to automatically fill those+-- in, then see 'disintegrate'.+--+-- N.B., the resulting functions from @a@ to @'HMeasure b@ are+-- indeed measurable, thus it is safe\/appropriate to use Hakaru's+-- @(':->)@ rather than Haskell's @(->)@.+--+-- BUG: Actually, disintegration is with respect to the /Borel/+-- measure on the first component of the pair! Alas, we don't really+-- have a clean way of describing this since we've no primitive+-- 'MeasureOp' for Borel measures.+--+-- /Developer's Note:/ This function fills the role that the old+-- @runDisintegrate@ did (as opposed to the old function called+-- @disintegrate@). [Once people are familiar enough with the new+-- code base and no longer recall what the old code base was doing,+-- this note should be deleted.]+disintegrateWithVar+    :: (ABT Term abt)+    => Text.Text+    -> Sing a+    -> abt '[] ('HMeasure (HPair a b))+    -> [abt '[] (a ':-> 'HMeasure b)]+disintegrateWithVar hint typ m =+    let x = Variable hint (nextFreeOrBind m) typ+    in map (lam_ x) . flip runDis [Some2 m, Some2 (var x)] $ do+        ab <- perform m+#ifdef __TRACE_DISINTEGRATE__+        ss <- getStatements+        trace ("-- disintegrate: finished perform\n"+            ++ show (pretty_Statements ss PP.$+$ PP.sep(prettyPrec_ 11 ab))+            ++ "\n") $ return ()+#endif+        -- BUG: Why does 'testDisintegrate1a' return no solutions?+        --+        -- In older code (up to git#38889a5): It's because 'emitUnpair'+        -- isn't quite smart enough. When the @ab@ expression is a+        -- 'Neutral' case expression, we need to go underneath the+        -- case expression and call 'constrainValue' on each branch.+        -- Instead, what we currently do is emit an @unpair@ case+        -- statement with the scrutinee being the 'Neutral' case+        -- expression, and then just return the pair of variables+        -- bound by the emitted @unpair@; but, of course,+        -- 'constrainValue' can't do anything with those variables+        -- (since they appear to be free, given as they've already+        -- been emitted). Another way to think about what it is we+        -- need to do to correct this is that we need to perform+        -- the case-of-case transformation (where one of the cases+        -- is the 'Neutral' one, and the other is the @unpair@).+        --+        -- In newer code (git#e8a0c66 and later): When we call 'perform'+        -- on an 'SBind' statement we emit some code and update the+        -- binding to become an 'SLet' of some local variable to+        -- the emitted variable. Later on when we call 'constrainVariable'+        -- on the local variable, we will look that 'SLet' statement+        -- up; and then when we call 'constrainVariable' on the+        -- emitted variable, things will @bot@ because we cannot+        -- constrain free variables in general.+        (a,b) <- emitUnpair ab+#ifdef __TRACE_DISINTEGRATE__+        trace ("-- disintegrate: finished emitUnpair: "+            ++ show (pretty a, pretty b)) $ return ()+#endif+        constrainValue (var x) a+#ifdef __TRACE_DISINTEGRATE__+        ss <- getStatements+        locs <- getLocs+        traceM ("-- disintegrate: finished constrainValue\n"+                ++ show (pretty_Statements ss) ++ "\n"+                ++ show (prettyLocs locs)+               )+#endif+        return b+++-- | A variant of 'disintegrateWithVar' which automatically computes+-- the type via 'typeOf'.+disintegrate+    :: (ABT Term abt)+    => abt '[] ('HMeasure (HPair a b))+    -> [abt '[] (a ':-> 'HMeasure b)]+disintegrate m =+    disintegrateWithVar+        Text.empty+        (fst . sUnPair . sUnMeasure $ typeOf m) -- TODO: change the exception thrown form 'typeOf' so that we know it comes from here+        m+++-- | Return the density function for a given measure. The first two+-- arguments give the hint and type of the lambda-bound variable+-- in the result. If you want to automatically fill those in, then+-- see 'density'.+--+-- TODO: is the resulting function guaranteed to be measurable? If+-- so, update this documentation to reflect that fact; if not, then+-- we should make it into a Haskell function instead.+densityWithVar+    :: (ABT Term abt)+    => Text.Text+    -> Sing a+    -> abt '[] ('HMeasure a)+    -> [abt '[] (a ':-> 'HProb)]+densityWithVar hint typ m =+    let x = Variable hint (nextFree m `max` nextBind m) typ+    in (lam_ x . E.total) <$> observe m (var x)+++-- | A variant of 'densityWithVar' which automatically computes the+-- type via 'typeOf'.+density+    :: (ABT Term abt)+    => abt '[] ('HMeasure a)+    -> [abt '[] (a ':-> 'HProb)]+density m =+    densityWithVar+        Text.empty+        (sUnMeasure $ typeOf m)+        m+++-- | Constrain a measure such that it must return the observed+-- value. In other words, the resulting measure returns the observed+-- value with weight according to its density in the original+-- measure, and gives all other values weight zero.+observe+    :: (ABT Term abt)+    => abt '[] ('HMeasure a)+    -> abt '[] a+    -> [abt '[] ('HMeasure a)]+observe m x =+    runDis (constrainOutcome x m >> return x) [Some2 m, Some2 x]+++-- | Arbitrarily choose one of the possible alternatives. In the+-- future, this function should be replaced by a better one that+-- takes some sort of strategy for deciding which alternative to+-- choose.+determine :: (ABT Term abt) => [abt '[] a] -> Maybe (abt '[] a)+determine []    = Nothing+determine (m:_) = Just m+++----------------------------------------------------------------+----------------------------------------------------------------+firstM :: Functor f => (a -> f b) -> (a,c) -> f (b,c)+firstM f (x,y) = (\z -> (z, y)) <$> f x+++-- N.B., forward disintegration is not identical to partial evaluation,+-- as noted at the top of the file. For correctness we need to+-- ensure the result is emissible (i.e., has no heap-bound variables).+-- More specifically, we need to ensure emissibility in the places+-- where we call 'emitMBind'+evaluate_ :: (ABT Term abt) => TermEvaluator abt (Dis abt)+evaluate_ = evaluate perform evaluateCase+++-- Copying `evaluate` and `update` from LH.Evaluation.Lazy for now (2016-06-28)+-- Beginning of copied code -------------------------------------------------++evaluate+    :: forall abt m p+    .  (ABT Term abt)+    => MeasureEvaluator abt (Dis abt)+    -> (TermEvaluator abt (Dis abt) -> CaseEvaluator abt (Dis abt))+    -> TermEvaluator  abt (Dis abt)+{-# INLINE evaluate #-}+evaluate perform evaluateCase = goEvaluate+    where+    evaluateCase_ :: CaseEvaluator abt (Dis abt)+    evaluateCase_ = evaluateCase goEvaluate++    goEvaluate :: TermEvaluator abt (Dis abt)+    goEvaluate e0 =+#ifdef __TRACE_DISINTEGRATE__+      getIndices >>= \inds ->+      trace ("-- goEvaluate: " ++ show (pretty e0)+                               ++ "at " ++ show (ppInds inds)) $+#endif+      caseVarSyn e0 (update perform goEvaluate) $ \t ->+        case t of+        -- Things which are already WHNFs+        Literal_ v               -> return . Head_ $ WLiteral v+        Datum_   d               -> return . Head_ $ WDatum   d+        Empty_   typ             -> return . Head_ $ WEmpty   typ+        Array_   e1 e2           -> return . Head_ $ WArray e1 e2+        Lam_  :$ e1 :* End       -> return . Head_ $ WLam   e1+        Dirac :$ e1 :* End       -> return . Head_ $ WDirac e1+        MBind :$ e1 :* e2 :* End -> return . Head_ $ WMBind e1 e2+        Plate :$ e1 :* e2 :* End -> return . Head_ $ WPlate e1 e2+        MeasureOp_ o :$ es       -> return . Head_ $ WMeasureOp o es+        Superpose_ pes           -> return . Head_ $ WSuperpose pes+        Reject_ typ              -> return . Head_ $ WReject typ+        -- We don't bother evaluating these, even though we could...+        Integrate :$ e1 :* e2 :* e3 :* End ->+            return . Head_ $ WIntegrate e1 e2 e3+        Summate h1 h2 :$ e1 :* e2 :* e3 :* End ->+            return . Neutral $ syn t+            --return . Head_ $ WSummate   e1 e2 e3+++        -- Everything else needs some evaluation++        App_ :$ e1 :* e2 :* End -> do+            w1 <- goEvaluate e1+            case w1 of+                Neutral e1' -> return . Neutral $ P.app e1' e2+                Head_   v1  -> evaluateApp v1+            where+            evaluateApp (WLam f)   =+                -- call-by-name:+                caseBind f $ \x f' -> do+                    i <- getIndices+                    push (SLet x (Thunk e2) i) f' goEvaluate+            evaluateApp _ = error "evaluate{App_}: the impossible happened"++        Let_ :$ e1 :* e2 :* End -> do+            i <- getIndices+            caseBind e2 $ \x e2' ->+                push (SLet x (Thunk e1) i) e2' goEvaluate++        CoerceTo_   c :$ e1 :* End -> C.coerceTo   c <$> goEvaluate e1+        UnsafeFrom_ c :$ e1 :* End -> C.coerceFrom c <$> goEvaluate e1++        -- TODO: will maybe clean up the code to map 'evaluate' over @es@ before calling the evaluateFooOp helpers?+        NaryOp_  o    es -> evaluateNaryOp  goEvaluate o es+        ArrayOp_ o :$ es -> evaluateArrayOp goEvaluate o es+        PrimOp_  o :$ es -> evaluatePrimOp  goEvaluate o es++        -- BUG: avoid the chance of looping in case 'E.expect' residualizes!+        -- TODO: use 'evaluate' in 'E.expect' for the evaluation of @e1@+        Expect :$ e1 :* e2 :* End ->+            error "TODO: evaluate{Expect}: unclear how to handle this without cyclic dependencies"+        {-+        -- BUG: can't call E.expect because of cyclic dependency+            goEvaluate . E.expect e1 $ \e3 ->+                syn (Let_ :$ e3 :* e2 :* End)+        -}++        Case_ e bs -> evaluateCase_ e bs++        _ :$ _ -> error "evaluate: the impossible happened"++evaluateNaryOp+    :: (ABT Term abt)+    => TermEvaluator abt (Dis abt)+    -> NaryOp a+    -> Seq (abt '[] a)+    -> Dis abt (Whnf abt a)+evaluateNaryOp evaluate_ = \o es -> mainLoop o (evalOp o) S.empty es+    where+    -- TODO: there's got to be a more efficient way to do this...+    mainLoop o op ws es =+        case S.viewl es of+        S.EmptyL   -> return $+            case S.viewl ws of+            S.EmptyL         -> identityElement o -- Avoid empty naryOps+            w S.:< ws'+                | S.null ws' -> w -- Avoid singleton naryOps+                | otherwise    ->+                    Neutral . syn . NaryOp_ o $ fmap fromWhnf ws+        e S.:< es' -> do+            w <- evaluate_ e+            case matchNaryOp o w of+                Nothing  -> mainLoop o op (snocLoop op ws w) es'+                Just es2 -> mainLoop o op ws (es2 S.>< es')++    snocLoop+        :: (ABT syn abt)+        => (Head abt a -> Head abt a -> Head abt a)+        -> Seq (Whnf abt a)+        -> Whnf abt a+        -> Seq (Whnf abt a)+    snocLoop op ws w1 =+        -- TODO: immediately return @ws@ if @w1 == identityElement o@ (whenever identityElement is defined)+        case S.viewr ws of+        S.EmptyR    -> S.singleton w1+        ws' S.:> w2 ->+            case (w1,w2) of+            (Head_ v1, Head_ v2) -> snocLoop op ws' (Head_ (op v1 v2))+            _                    -> ws S.|> w1++    matchNaryOp+        :: (ABT Term abt)+        => NaryOp a+        -> Whnf abt a+        -> Maybe (Seq (abt '[] a))+    matchNaryOp o w =+        case w of+        Head_   _ -> Nothing+        Neutral e ->+            caseVarSyn e (const Nothing) $ \t ->+                case t of+                NaryOp_ o' es | o' == o -> Just es+                _                       -> Nothing++    -- TODO: move this off to Prelude.hs or somewhere...+    identityElement :: (ABT Term abt) => NaryOp a -> Whnf abt a+    identityElement o =+        case o of+        And    -> Head_ (WDatum dTrue)+        Or     -> Head_ (WDatum dFalse)+        Xor    -> Head_ (WDatum dFalse)+        Iff    -> Head_ (WDatum dTrue)+        Min  _ -> Neutral (syn (NaryOp_ o S.empty)) -- no identity in general (but we could do it by cases...)+        Max  _ -> Neutral (syn (NaryOp_ o S.empty)) -- no identity in general (but we could do it by cases...)+        -- TODO: figure out how to reuse 'P.zero_' and 'P.one_' here; requires converting thr @(syn . Literal_)@ into @(Head_ . WLiteral)@. Maybe we should change 'P.zero_' and 'P.one_' so they just return the 'Literal' itself rather than the @abt@?+        Sum  HSemiring_Nat  -> Head_ (WLiteral (LNat  0))+        Sum  HSemiring_Int  -> Head_ (WLiteral (LInt  0))+        Sum  HSemiring_Prob -> Head_ (WLiteral (LProb 0))+        Sum  HSemiring_Real -> Head_ (WLiteral (LReal 0))+        Prod HSemiring_Nat  -> Head_ (WLiteral (LNat  1))+        Prod HSemiring_Int  -> Head_ (WLiteral (LInt  1))+        Prod HSemiring_Prob -> Head_ (WLiteral (LProb 1))+        Prod HSemiring_Real -> Head_ (WLiteral (LReal 1))++    -- | The evaluation interpretation of each NaryOp+    evalOp+        :: (ABT Term abt)+        => NaryOp a+        -> Head abt a+        -> Head abt a+        -> Head abt a+    -- TODO: something more efficient\/direct if we can...+    evalOp And      = \v1 v2 -> reflect (reify v1 && reify v2)+    evalOp Or       = \v1 v2 -> reflect (reify v1 || reify v2)+    evalOp Xor      = \v1 v2 -> reflect (reify v1 /= reify v2)+    evalOp Iff      = \v1 v2 -> reflect (reify v1 == reify v2)+    evalOp (Min  _) = error "TODO: evalOp{Min}"+    evalOp (Max  _) = error "TODO: evalOp{Max}"+    {-+    evalOp (Min  _) = \v1 v2 -> reflect (reify v1 `min` reify v2)+    evalOp (Max  _) = \v1 v2 -> reflect (reify v1 `max` reify v2)+    evalOp (Sum  _) = \v1 v2 -> reflect (reify v1 + reify v2)+    evalOp (Prod _) = \v1 v2 -> reflect (reify v1 * reify v2)+    -}+    -- HACK: this is just to have something to test. We really should reduce\/remove all this boilerplate...+    evalOp (Sum  theSemi) =+        \(WLiteral v1) (WLiteral v2) -> WLiteral $ evalSum  theSemi v1 v2+    evalOp (Prod theSemi) =+        \(WLiteral v1) (WLiteral v2) -> WLiteral $ evalProd theSemi v1 v2++    -- TODO: even if only one of the arguments is a literal, if that literal is zero\/one, then we can still partially evaluate it. (As is done in the old finally-tagless code)+    evalSum, evalProd :: HSemiring a -> Literal a -> Literal a -> Literal a+    evalSum  HSemiring_Nat  = \(LNat  n1) (LNat  n2) -> LNat  (n1 + n2)+    evalSum  HSemiring_Int  = \(LInt  i1) (LInt  i2) -> LInt  (i1 + i2)+    evalSum  HSemiring_Prob = \(LProb p1) (LProb p2) -> LProb (p1 + p2)+    evalSum  HSemiring_Real = \(LReal r1) (LReal r2) -> LReal (r1 + r2)+    evalProd HSemiring_Nat  = \(LNat  n1) (LNat  n2) -> LNat  (n1 * n2)+    evalProd HSemiring_Int  = \(LInt  i1) (LInt  i2) -> LInt  (i1 * i2)+    evalProd HSemiring_Prob = \(LProb p1) (LProb p2) -> LProb (p1 * p2)+    evalProd HSemiring_Real = \(LReal r1) (LReal r2) -> LReal (r1 * r2)++isIndex :: (ABT Term abt) => Variable 'HNat -> Dis abt Bool+isIndex v = do inds <- getIndices+               return $ v `elem` map indVar inds                              ++-- | For {evaluate, constrainValue v0} ArrayOp_ (Index _) :$ e1 :* e2 :* End+indexArrayOp :: forall abt typs args a r+             .  ( ABT Term abt+                , typs ~ UnLCs args, args ~ LCs typs )+             => ArrayOp typs a+             -> SArgs abt args+             -> TermEvaluator abt (Dis abt)+             -> (abt '[] a -> Dis abt r) -- evaluate or (constrainValue v0)+             -> (Head abt ('HArray a)    -- e1 is in whnf, and+                -> Variable 'HNat        -- e2 is a free under current indices+                -> Dis abt r)+             -> (Term abt ('HArray a)    -- e1 is neutral syntax+                -> Dis abt r)+             -> (abt '[] ('HArray a)     -- e1 is a free variable+                -> Dis abt r) +             -> (abt '[] ('HArray a)     -- e1 is a multiloc, and+                -> Variable 'HNat        -- e2 is a free under current indices+                -> Dis abt r)+             -> Dis abt r+indexArrayOp o@(Index _) (e1 :* e2 :* End) evaluate_ kInd kArr kSyn kFree kMultiLoc = do+  w1 <- evaluate_ e1+  case w1 of+    Head_ arr@(WArray _ b) -> caseBind b $ \x body ->+      evalIndex (kInd . flip (rename x) body) (kArr arr)+    Head_ (WEmpty _) -> error "TODO: indexArrayOp o (Empty_ :* _ :* End)"+    Head_ _          -> error "indexArrayOp: unknown whnf of array type"+    Neutral e1' -> flip (caseVarSyn e1') kSyn $ \x ->+      do locs <- getLocs+         case (lookupAssoc x locs) of+           Nothing              -> kFree e1'+           Just (Loc _ _)       -> error "indexArrayOp: impossible, we have a Neutral term"+           Just (MultiLoc l js) ->+             evalIndex ((kInd . var =<<) . mkLoc Text.empty l . flip extendLocInds js)+                       (kMultiLoc e1')+    where+      evalIndex :: (ABT Term abt)+                => (Variable 'HNat -> Dis abt r)+                -> (Variable 'HNat -> Dis abt r)+                -> Dis abt r+      evalIndex thenCase elseCase = do+            w2 <- evaluate_ e2+            caseWhnf w2 (const bot) $ \term -> -- bot if index is in whnf (eg. a literal num)+              flip (caseVarSyn term) (const bot) $ \v -> -- bot if index is neutral syntax+                do isInd <- isIndex v+                   if isInd then thenCase v else elseCase v+indexArrayOp _ _ _ _ _ _ _ _ = error "indexArrayOp called on incorrect ArrayOp"++evaluateArrayOp+    :: ( ABT Term abt+       , typs ~ UnLCs args, args ~ LCs typs)+    => TermEvaluator abt (Dis abt)+    -> ArrayOp typs a+    -> SArgs abt args+    -> Dis abt (Whnf abt a)+evaluateArrayOp evaluate_ = go+    where+    go o@(Index _) = \args@(_ :* e2 :* End) ->+      let returnIndex = return . Neutral . syn+      in indexArrayOp o args+                      evaluate_+                      evaluate_+                      (\arr v -> returnIndex (ArrayOp_ o :$ fromHead arr :* var v :* End))+                      (\s     -> returnIndex (ArrayOp_ o :$ syn s        :* e2    :* End))+                      (\e1'   -> returnIndex (ArrayOp_ o :$ e1'          :* e2    :* End))+                      (\e1' v -> returnIndex (ArrayOp_ o :$ e1'          :* var v :* End))+                   +    go o@(Size _) = \(e1 :* End) -> do+        w1 <- evaluate_ e1+        case w1 of+            Neutral e1' -> return . Neutral $ syn (ArrayOp_ o :$ e1' :* End)+            Head_   v1  ->+                case head2array v1 of+                WAEmpty      -> return . Head_ $ WLiteral (LNat 0)+                WAArray e3 _ -> evaluate_ e3++    go (Reduce _) = \(e1 :* e2 :* e3 :* End) ->+        error "TODO: evaluateArrayOp{Reduce}"+++data ArrayHead :: ([Hakaru] -> Hakaru -> *) -> Hakaru -> * where+    WAEmpty :: ArrayHead abt a+    WAArray+        :: !(abt '[] 'HNat)+        -> !(abt '[ 'HNat] a)+        -> ArrayHead abt a++head2array :: Head abt ('HArray a) -> ArrayHead abt a+head2array (WEmpty _)     = WAEmpty+head2array (WArray e1 e2) = WAArray e1 e2++impl, diff, nand, nor :: Bool -> Bool -> Bool+impl x y = not x || y+diff x y = x && not y+nand x y = not (x && y)+nor  x y = not (x || y)                            ++evaluatePrimOp+    :: forall abt p typs args a+    .  ( ABT Term abt+       , typs ~ UnLCs args, args ~ LCs typs)+    => TermEvaluator abt (Dis abt)+    -> PrimOp typs a+    -> SArgs abt args+    -> Dis abt (Whnf abt a)+evaluatePrimOp evaluate_ = go+    where+    -- HACK: we don't have any way of saying these functions haven't reduced even though it's not actually a neutral term.+    neu1 :: forall b c+        .  (abt '[] b -> abt '[] c)+        -> abt '[] b+        -> Dis abt (Whnf abt c)+    neu1 f e = (Neutral . f . fromWhnf) <$> evaluate_ e++    neu2 :: forall b c d+        .  (abt '[] b -> abt '[] c -> abt '[] d)+        -> abt '[] b+        -> abt '[] c   +        -> Dis abt (Whnf abt d)+    neu2 f e1 e2 = do e1' <- fromWhnf <$> evaluate_ e1+                      e2' <- fromWhnf <$> evaluate_ e2+                      return . Neutral $ f e1' e2'++    rr1 :: forall b b' c c'+        .  (Interp b b', Interp c c')+        => (b' -> c')+        -> (abt '[] b -> abt '[] c)+        -> abt '[] b+        -> Dis abt (Whnf abt c)+    rr1 f' f e = do+        w <- evaluate_ e+        return $+            case w of+            Neutral e' -> Neutral $ f e'+            Head_   v  -> Head_ . reflect $ f' (reify v)++    rr2 :: forall b b' c c' d d'+        .  (Interp b b', Interp c c', Interp d d')+        => (b' -> c' -> d')+        -> (abt '[] b -> abt '[] c -> abt '[] d)+        -> abt '[] b+        -> abt '[] c+        -> Dis abt (Whnf abt d)+    rr2 f' f e1 e2 = do+        w1 <- evaluate_ e1+        w2 <- evaluate_ e2+        return $+            case w1 of+            Neutral e1' -> Neutral $ f e1' (fromWhnf w2)+            Head_   v1  ->+                case w2 of+                Neutral e2' -> Neutral $ f (fromWhnf w1) e2'+                Head_   v2  -> Head_ . reflect $ f' (reify v1) (reify v2)++    primOp2_+        :: forall b c d+        .  PrimOp '[ b, c ] d -> abt '[] b -> abt '[] c -> abt '[] d+    primOp2_ o e1 e2 = syn (PrimOp_ o :$ e1 :* e2 :* End)++    -- TODO: something more efficient\/direct if we can...+    go Not  (e1 :* End)       = rr1 not  P.not  e1+    go Impl (e1 :* e2 :* End) = rr2 impl (primOp2_ Impl) e1 e2+    go Diff (e1 :* e2 :* End) = rr2 diff (primOp2_ Diff) e1 e2+    go Nand (e1 :* e2 :* End) = rr2 nand P.nand e1 e2+    go Nor  (e1 :* e2 :* End) = rr2 nor  P.nor  e1 e2++    -- HACK: we don't have a way of saying that 'Pi' (or 'Infinity',...) is in fact a head; so we're forced to call it neutral which is a lie. We should add constructor(s) to 'Head' to cover these magic constants; probably grouped together under a single constructor called something like @Constant@. Maybe should group them like that in the AST as well?+    go Pi        End               = return $ Neutral P.pi++    -- We treat trig functions as strict, thus forcing their+    -- arguments; however, to avoid fuzz issues we don't actually+    -- evaluate the trig functions.+    --+    -- HACK: we might should have some other way to make these+    -- 'Whnf' rather than calling them neutral terms; since they+    -- aren't, in fact, neutral!+    go Sin       (e1 :* End)       = neu1 P.sin   e1+    go Cos       (e1 :* End)       = neu1 P.cos   e1+    go Tan       (e1 :* End)       = neu1 P.tan   e1+    go Asin      (e1 :* End)       = neu1 P.asin  e1+    go Acos      (e1 :* End)       = neu1 P.acos  e1+    go Atan      (e1 :* End)       = neu1 P.atan  e1+    go Sinh      (e1 :* End)       = neu1 P.sinh  e1+    go Cosh      (e1 :* End)       = neu1 P.cosh  e1+    go Tanh      (e1 :* End)       = neu1 P.tanh  e1+    go Asinh     (e1 :* End)       = neu1 P.asinh e1+    go Acosh     (e1 :* End)       = neu1 P.acosh e1+    go Atanh     (e1 :* End)       = neu1 P.atanh e1++    -- TODO: deal with how we have better types for these three ops than Haskell does...+    -- go RealPow   (e1 :* e2 :* End) = rr2 (**) (P.**) e1 e2+    go RealPow   (e1 :* e2 :* End) = neu2 (P.**) e1 e2++    -- HACK: these aren't actually neutral!+    -- BUG: we should try to cancel out @(exp . log)@ and @(log . exp)@+    go Exp       (e1 :* End)       = neu1 P.exp e1+    go Log       (e1 :* End)       = neu1 P.log e1++    -- HACK: these aren't actually neutral!+    go (Infinity h)     End        =+        case h of+          HIntegrable_Nat  -> return . Neutral $ P.primOp0_ (Infinity h)+          HIntegrable_Prob -> return $ Neutral P.infinity++    go GammaFunc   (e1 :* End)            = neu1 P.gammaFunc e1+    go BetaFunc    (e1 :* e2 :* End)      = neu2 P.betaFunc  e1 e2++    go (Equal  theEq)   (e1 :* e2 :* End) = rrEqual theEq  e1 e2+    go (Less   theOrd)  (e1 :* e2 :* End) = rrLess  theOrd e1 e2+    go (NatPow theSemi) (e1 :* e2 :* End) =+        case theSemi of+        HSemiring_Nat    -> rr2 (\v1 v2 -> v1 ^ fromNatural v2) (P.^) e1 e2+        HSemiring_Int    -> rr2 (\v1 v2 -> v1 ^ fromNatural v2) (P.^) e1 e2+        HSemiring_Prob   -> rr2 (\v1 v2 -> v1 ^ fromNatural v2) (P.^) e1 e2+        HSemiring_Real   -> rr2 (\v1 v2 -> v1 ^ fromNatural v2) (P.^) e1 e2+    go (Negate theRing) (e1 :* End) =+        case theRing of+        HRing_Int        -> rr1 negate P.negate e1+        HRing_Real       -> rr1 negate P.negate e1+    go (Abs    theRing) (e1 :* End) =+        case theRing of+        HRing_Int        -> rr1 (unsafeNatural . abs) P.abs_ e1+        HRing_Real       -> rr1 (unsafeNonNegativeRational  . abs) P.abs_ e1+    go (Signum theRing) (e1 :* End) =+        case theRing of+        HRing_Int        -> rr1 signum P.signum e1+        HRing_Real       -> rr1 signum P.signum e1+    go (Recip  theFractional) (e1 :* End) =+        case theFractional of+        HFractional_Prob -> rr1 recip  P.recip  e1+        HFractional_Real -> rr1 recip  P.recip  e1+    go (NatRoot theRadical) (e1 :* e2 :* End) =+        case theRadical of+        HRadical_Prob -> neu2 (flip P.thRootOf) e1 e2+    {-+    go (NatRoot theRadical) (e1 :* e2 :* End) =+        case theRadical of+        HRadical_Prob -> rr2 natRoot (flip P.thRootOf) e1 e2+    go (Erf theContinuous) (e1 :* End) =+        case theContinuous of+        HContinuous_Prob -> rr1 erf P.erf e1+        HContinuous_Real -> rr1 erf P.erf e1+    -}+    go op _ = error $ "TODO: evaluatePrimOp{" ++ show op ++ "}"+++    rrEqual+        :: forall b. HEq b -> abt '[] b -> abt '[] b -> Dis abt (Whnf abt HBool)+    rrEqual theEq =+        case theEq of+        HEq_Nat    -> rr2 (==) (P.==)+        HEq_Int    -> rr2 (==) (P.==)+        HEq_Prob   -> rr2 (==) (P.==)+        HEq_Real   -> rr2 (==) (P.==)+        HEq_Array aEq -> error "TODO: rrEqual{HEq_Array}"+        HEq_Bool   -> rr2 (==) (P.==)+        HEq_Unit   -> rr2 (==) (P.==)+        HEq_Pair   aEq bEq ->+            \e1 e2 -> do+                w1 <- evaluate_ e1+                w2 <- evaluate_ e2+                case w1 of+                    Neutral e1' ->+                        return . Neutral+                            $ P.primOp2_ (Equal theEq) e1' (fromWhnf w2)+                    Head_   v1  ->+                        case w2 of+                        Neutral e2' ->+                            return . Neutral+                                $ P.primOp2_ (Equal theEq) (fromHead v1) e2'+                        Head_ v2 -> do+                            let (v1a, v1b) = reifyPair v1+                            let (v2a, v2b) = reifyPair v2+                            wa <- rrEqual aEq v1a v2a+                            wb <- rrEqual bEq v1b v2b+                            return $+                                case wa of+                                Neutral ea ->+                                    case wb of+                                    Neutral eb -> Neutral (ea P.&& eb)+                                    Head_   vb+                                        | reify vb  -> wa+                                        | otherwise -> Head_ $ WDatum dFalse+                                Head_ va+                                    | reify va  -> wb+                                    | otherwise -> Head_ $ WDatum dFalse++        HEq_Either aEq bEq -> error "TODO: rrEqual{HEq_Either}"++    rrLess+        :: forall b. HOrd b -> abt '[] b -> abt '[] b -> Dis abt (Whnf abt HBool)+    rrLess theOrd =+        case theOrd of+        HOrd_Nat    -> rr2 (<) (P.<)+        HOrd_Int    -> rr2 (<) (P.<)+        HOrd_Prob   -> rr2 (<) (P.<)+        HOrd_Real   -> rr2 (<) (P.<)+        HOrd_Array aOrd -> error "TODO: rrLess{HOrd_Array}"+        HOrd_Bool   -> rr2 (<) (P.<)+        HOrd_Unit   -> rr2 (<) (P.<)+        HOrd_Pair aOrd bOrd ->+            \e1 e2 -> do+                w1 <- evaluate_ e1+                w2 <- evaluate_ e2+                case w1 of+                    Neutral e1' ->+                        return . Neutral+                            $ P.primOp2_ (Less theOrd) e1' (fromWhnf w2)+                    Head_   v1  ->+                        case w2 of+                        Neutral e2' ->+                            return . Neutral+                                $ P.primOp2_ (Less theOrd) (fromHead v1) e2'+                        Head_ v2 -> do+                            let (v1a, v1b) = reifyPair v1+                            let (v2a, v2b) = reifyPair v2+                            error "TODO: rrLess{HOrd_Pair}"+                            -- BUG: The obvious recursion won't work because we need to know when the first components are equal before recursing (to implement lexicographic ordering). We really need a ternary comparison operator like 'compare'.+        HOrd_Either aOrd bOrd -> error "TODO: rrLess{HOrd_Either}"+                  +update+    :: forall abt+    .  (ABT Term abt)+    => MeasureEvaluator  abt (Dis abt)+    -> TermEvaluator     abt (Dis abt)+    -> VariableEvaluator abt (Dis abt)+update perform evaluate_ x =+    do locs <- getLocs+    -- If we get 'Nothing', then it turns out @x@ is a free variable+       maybe (return $ Neutral (var x)) lookForLoc (lookupAssoc x locs)+    where lookForLoc (Loc      l jxs) =+            (maybe (freeLocError l) return =<<) . select l $ \s ->+                case s of+                SBind l' e ixs -> do+                  Refl <- varEq l l'+                  Just $ do+                    w <- withIndices ixs $ perform (caseLazy e fromWhnf id)+                    unsafePush (SLet l (Whnf_ w) ixs)+#ifdef __TRACE_DISINTEGRATE__+                    trace ("-- updated "+                           ++ show (ppStatement 11 s)+                           ++ " to "+                           ++ show (ppStatement 11 (SLet l (Whnf_ w) ixs))+                          ) $ return ()+#endif+                    let as = toAssocs $ zipWith Assoc (map indVar ixs) jxs+                        w' = renames as (fromWhnf w)+                    inds <- getIndices+                    withIndices inds $ return (fromMaybe (Neutral w') (toWhnf w'))+                SLet  l' e ixs -> do+                  Refl <- varEq l l'+                  Just $ do+                    w <- withIndices ixs $ caseLazy e return evaluate_+                    unsafePush (SLet l (Whnf_ w) ixs)+                    let as = toAssocs $ zipWith Assoc (map indVar ixs) jxs+                        w' = renames as (fromWhnf w)+                    inds <- getIndices+                    withIndices inds $ return (fromMaybe (Neutral w') (toWhnf w'))+                -- This does not bind any variables, so it definitely can't match.+                SWeight   _ _ -> Nothing+                -- This does bind variables,+                -- but there's no expression we can return for it+                -- because the variables are untouchable\/abstract.+                SGuard ls pat scrutinee i -> Just . return . Neutral $ var x++          -- Case for MultiLocs+          lookForLoc (MultiLoc l jxs) = return (Neutral $ var x)+                      +---------------------------------------------------------- End of copied code --+                 ++-- | The forward disintegrator's function for evaluating case+-- expressions. First we try calling 'defaultCaseEvaluator' which+-- will evaluate the scrutinee and select the matching branch (if+-- any). But that doesn't work out in general, since the scrutinee+-- may contain heap-bound variables. So our fallback definition+-- will push a 'SGuard' onto the heap and then continue evaluating+-- each branch (thereby duplicating the continuation, calling it+-- once on each branch).+evaluateCase+    :: forall abt+    .  (ABT Term abt)+    => TermEvaluator abt (Dis abt)+    -> CaseEvaluator abt (Dis abt)+{-# INLINE evaluateCase #-}+evaluateCase evaluate_ = evaluateCase_+    where+    evaluateCase_ :: CaseEvaluator abt (Dis abt)+    evaluateCase_ e bs =+        defaultCaseEvaluator evaluate_ e bs+        <|> evaluateBranches e bs++    evaluateBranches :: CaseEvaluator abt (Dis abt)+    evaluateBranches e = choose . map evaluateBranch+        where+        evaluateBranch (Branch pat body) =+            let (vars,body') = caseBinds body+            in getIndices >>= \i ->+                push (SGuard vars pat (Thunk e) i) body' evaluate_+++evaluateDatum :: (ABT Term abt) => DatumEvaluator (abt '[]) (Dis abt)+evaluateDatum e = viewWhnfDatum <$> evaluate_ e++-- | Simulate performing 'HMeasure' actions by simply emiting code+-- for those actions, returning the bound variable.+--+-- This is the function called @(|>>)@ in the disintegration paper.+perform :: forall abt. (ABT Term abt) => MeasureEvaluator abt (Dis abt)+perform = \e0 ->+#ifdef __TRACE_DISINTEGRATE__+    getStatements >>= \ss ->+    getLocs >>= \locs ->+    getIndices >>= \inds ->+    trace ("\n-- perform --\n"+        ++ "at " ++ show (ppInds inds) ++ "\n"+        ++ show (prettyLocs locs) ++ "\n"+        ++ show (pretty_Statements_withTerm ss e0)+        ++ "\n") $+#endif+    caseVarSyn e0 performVar performTerm+    where+    performTerm :: forall a. Term abt ('HMeasure a) -> Dis abt (Whnf abt a)+    performTerm (Dirac :$ e1 :* End)       = evaluate_ e1+    performTerm (MeasureOp_ o :$ es)       = performMeasureOp o es+    performTerm (MBind :$ e1 :* e2 :* End) =+        caseBind e2 $ \x e2' -> do+            inds <- getIndices+            push (SBind x (Thunk e1) inds) e2' perform++    performTerm (Plate :$ e1 :* e2 :* End) =  do+      x1 <- pushPlate e1 e2+      return (Neutral (var x1))++    performTerm (Superpose_ pes) = do+        inds <- getIndices+        if not (null inds) && L.length pes > 1 then bot else+          emitFork_ (P.superpose . fmap ((,) P.one))+                    (fmap (\(p,e) -> push (SWeight (Thunk p) inds) e perform)+                          pes)++    -- Avoid falling through to the @performWhnf <=< evaluate_@ case+    performTerm (Let_ :$ e1 :* e2 :* End) =+        caseBind e2 $ \x e2' -> do+            inds <- getIndices+            push (SLet x (Thunk e1) inds) e2' perform++    -- TODO: we could optimize this by calling some @evaluateTerm@+    -- directly, rather than calling 'syn' to rebuild @e0@ from+    -- @t0@ and then calling 'evaluate_' (which will just use+    -- 'caseVarSyn' to get the @t0@ back out from the @e0@).+    --+    -- BUG: when @t0@ is a 'Case_', this doesn't work right. This+    -- is the source of the hygiene bug in 'testPerform1b'. Alas,+    -- we cannot use 'emitCaseWith' here since that would require+    -- the scrutinee to be emissible; but we'd want something pretty+    -- similar...+    performTerm t0 = do+        w <- evaluate_ (syn t0)+#ifdef __TRACE_DISINTEGRATE__+        trace ("-- perform: finished evaluate, with:\n" ++ show (PP.sep(prettyPrec_ 11 w))) $ return ()+#endif+        performWhnf w+++    performVar :: forall a. Variable ('HMeasure a) -> Dis abt (Whnf abt a)+    performVar = performWhnf <=< update perform evaluate_++    -- BUG: it's not clear this is actually doing the right thing for its call-sites. In particular, we should handle 'Case_' specially, to deal with the hygiene bug in 'testPerform1b'...+    --+    -- BUG: found the 'testPerform1b' hygiene bug! We can't simply call 'emitMBind' on @e@, because @e@ may not be emissible!+    performWhnf+        :: forall a. Whnf abt ('HMeasure a) -> Dis abt (Whnf abt a)+    performWhnf (Head_   v) = perform $ fromHead v+    performWhnf (Neutral e) = (Neutral . var) <$> emitMBind e+++    -- TODO: right now we do the simplest thing. However, for better+    -- coverage and cleaner produced code we'll need to handle each+    -- of the ops separately. (For example, see how 'Uniform' is+    -- handled in the old code; how it has two options for what to+    -- do.)+    performMeasureOp+        :: forall typs args a+        .  (typs ~ UnLCs args, args ~ LCs typs)+        => MeasureOp typs a+        -> SArgs abt args+        -> Dis abt (Whnf abt a)+    performMeasureOp = \o es -> nice o es <|> complete o es+        where+        -- Try to generate nice pretty output.+        nice+            :: MeasureOp typs a+            -> SArgs abt args+            -> Dis abt (Whnf abt a)+        nice o es = do+            es' <- traverse21 atomizeCore es+            x   <- emitMBind $ syn (MeasureOp_ o :$ es')+            return (Neutral $ var x)++        -- Try to be as complete as possible (i.e., 'bot' as little as possible), no matter how ugly the output code gets.+        complete+            :: MeasureOp typs a+            -> SArgs abt args+            -> Dis abt (Whnf abt a)+        complete Normal = \(mu :* sd :* End) -> do+            x <- var <$> emitMBind P.lebesgue+            pushWeight (P.densityNormal mu sd x)+            return (Neutral x)+        complete Uniform = \(lo :* hi :* End) -> do+            x <- var <$> emitMBind P.lebesgue+            pushGuard (lo P.< x P.&& x P.< hi)+            pushWeight (P.densityUniform lo hi x)+            return (Neutral x)+        complete _ = \_ -> bot++-- Calls unsafePush +pushWeight :: (ABT Term abt) => abt '[] 'HProb -> Dis abt ()+pushWeight w = do+  inds <- getIndices+  unsafePush $ SWeight (Thunk w) inds++-- Calls unsafePush +pushGuard :: (ABT Term abt) => abt '[] HBool -> Dis abt ()+pushGuard b = do+  inds <- getIndices+  unsafePush $ SGuard Nil1 pTrue (Thunk b) inds+                               ++-- | The goal of this function is to ensure the correctness criterion+-- that given any term to be emitted, the resulting term is+-- semantically equivalent but contains no heap-bound variables.+-- That correctness criterion is necessary to ensure hygiene\/scoping.+--+-- This particular implementation calls 'evaluate' recursively,+-- giving us something similar to full-beta reduction. However,+-- that is considered an implementation detail rather than part of+-- the specification of what the function should do. Also, it's a+-- gross hack and prolly a big part of why we keep running into+-- infinite looping issues.+--+-- This name is taken from the old finally tagless code, where+-- \"atomic\" terms are (among other things) emissible; i.e., contain+-- no heap-bound variables.+--+-- BUG: this function infinitely loops in certain circumstances+-- (namely when dealing with neutral terms)+atomize :: (ABT Term abt) => TermEvaluator abt (Dis abt)+atomize e =+#ifdef __TRACE_DISINTEGRATE__+    trace ("\n-- atomize --\n" ++ show (pretty e)) $+#endif+    traverse21 atomizeCore =<< evaluate_ e+++-- | A variant of 'atomize' which is polymorphic in the locally+-- bound variables @xs@ (whereas 'atomize' requires @xs ~ '[]@).+-- We factored this out because we often want this more polymorphic+-- variant when using our indexed @TraversableMN@ classes.+atomizeCore :: (ABT Term abt) => abt xs a -> Dis abt (abt xs a)+atomizeCore e = do+    -- HACK: this check for 'disjointVarSet' is sufficient to catch+    -- the particular infinite loops we were encountering, but it+    -- will not catch all of them. If the call to 'evaluate_' in+    -- 'atomize' returns a neutral term which contains heap-bound+    -- variables, then we'll still loop forever since we don't+    -- traverse\/fmap over the top-level term constructor of neutral+    -- terms.+    xs <- getHeapVars+    if disjointVarSet xs (freeVars e)+        then return e+        else+            let (ys, e') = caseBinds e+            in  (binds_ ys . fromWhnf) <$> atomize e'+    where+    -- TODO: does @IM.null . IM.intersection@ fuse correctly?+    disjointVarSet xs ys =+        IM.null (IM.intersection (unVarSet xs) (unVarSet ys))++-- HACK: if we really want to go through with this approach, then+-- we should memoize the set of heap-bound variables in the+-- 'ListContext' itself rather than recomputing it every time!+getHeapVars :: Dis abt (VarSet ('KProxy :: KProxy Hakaru))+getHeapVars =+    Dis $ \_ c h -> c (foldMap statementVars (statements h)) h++----------------------------------------------------------------+----------------------------------------------------------------+-- | Given an emissible term @v0@ (the first argument) and another+-- term @e0@ (the second argument), compute the constraints such+-- that @e0@ must evaluate to @v0@. This is the function called+-- @(<|)@ in the disintegration paper, though notably we swap the+-- argument order so that the \"value\" is the first argument.+--+-- N.B., this function assumes (and does not verify) that the first+-- argument is emissible. So callers (including recursive calls)+-- must guarantee this invariant, by calling 'atomize' as necessary.+--+-- TODO: capture the emissibility requirement on the first argument+-- in the types, to help avoid accidentally passing the arguments+-- in the wrong order!+constrainValue :: (ABT Term abt) => abt '[] a -> abt '[] a -> Dis abt ()+constrainValue v0 e0 =+#ifdef __TRACE_DISINTEGRATE__+    getStatements >>= \ss ->+    getLocs >>= \locs ->+    getIndices >>= \inds ->+    trace ("\n-- constrainValue: " ++ show (pretty v0) ++ "\n"           +        ++ show (pretty_Statements_withTerm ss e0) ++ "\n"+        ++ "at " ++ show (ppInds inds) ++ "\n"+        ++ show (prettyLocs locs) ++ "\n"+          ) $+#endif+    caseVarSyn e0 (constrainVariable v0) $ \t ->+        case t of+        -- There's a bunch of stuff we don't even bother trying to handle+        Empty_   _               -> error "TODO: disintegrate arrays"+        Array_   n e             ->+            caseBind e $ \x body -> do j <- freshInd n+                                       let x'    = indVar j+                                           body' = rename x x' body+                                       inds <- getIndices+                                       withIndices (extendIndices j inds) $+                                                   constrainValue (v0 P.! (var x')) body'+                                                   -- TODO use meta-index+        ArrayOp_ o@(Index _) :$ args -> indexArrayOp o args+                                                     evaluate_+                                                     (constrainValue v0)+                                                     (const $ const bot)+                                                     (const bot)+                                                     (const bot)+                                                     (const $ const bot)+          +        ArrayOp_ _ :$ _          -> error "TODO: disintegrate arrays"+        Lam_  :$ _  :* End       -> error "TODO: disintegrate lambdas"+        App_  :$ _  :* _ :* End  -> error "TODO: disintegrate lambdas"+        Integrate :$ _ :* _ :* _ :* End ->+            error "TODO: disintegrate integration"+        Summate _ _ :$ _ :* _ :* _ :* End ->+            error "TODO: disintegrate integration"+++        -- N.B., the semantically correct definition is:+        --+        -- > Literal_ v+        -- >     | "dirac v has a density wrt the ambient measure" -> ...+        -- >     | otherwise -> bot+        --+        -- For the case where the ambient measure is Lebesgue, dirac+        -- doesn't have a density, so we return 'bot'. However, we+        -- will need to generalize this when we start handling other+        -- ambient measures.+        Literal_ v               -> bot -- unsolvable. (kinda; see note)+        Datum_   d               -> constrainDatum v0 d+        Dirac :$ _ :* End        -> bot -- giving up.+        MBind :$ _ :* _ :* End   -> bot -- giving up.+        MeasureOp_ o :$ es       -> constrainValueMeasureOp v0 o es+        Superpose_ pes           -> bot -- giving up.+        Reject_ _                -> bot -- giving up.+        Let_ :$ e1 :* e2 :* End ->+            caseBind e2 $ \x e2' ->+                push (SLet x (Thunk e1) []) e2' (constrainValue v0)++        CoerceTo_   c :$ e1 :* End ->+            -- TODO: we need to insert some kind of guard that says+            -- @v0@ is in the range of @coerceTo c@, or equivalently+            -- that @unsafeFrom c v0@ will always succeed. We need+            -- to emit this guard (for correctness of the generated+            -- program) because if @v0@ isn't in the range of the+            -- coercion, then there's no possible way the program+            -- @e1@ could in fact be observed at @v0@. The only+            -- question is how to perform that check; for the+            -- 'Signed' coercions it's easy enough, but for the+            -- 'Continuous' coercions it's not really clear.+            constrainValue (P.unsafeFrom_ c v0) e1+        UnsafeFrom_ c :$ e1 :* End ->+            -- TODO: to avoid returning garbage, we'd need to place+            -- some constraint on @e1@ so that if the original+            -- program would've crashed due to a bad unsafe-coercion,+            -- then we won't return a disintegrated program (since+            -- it too should always crash). Avoiding this check is+            -- sound (i.e., if the input program is well-formed+            -- then the output program is a well-formed disintegration),+            -- it just overgeneralizes.+            constrainValue  (P.coerceTo_ c v0) e1+        NaryOp_     o    es        -> constrainNaryOp v0 o es+        PrimOp_     o :$ es        -> constrainPrimOp v0 o es+        Expect  :$ e1 :* e2 :* End -> error "TODO: constrainValue{Expect}"++        Case_ e bs ->+            -- First we try going forward on the scrutinee, to make+            -- pretty resulting programs; but if that doesn't work+            -- out, we fall back to just constraining the branches.+            do  match <- matchBranches evaluateDatum e bs+                case match of+                    Nothing ->+                        -- If desired, we could return the Hakaru program+                        -- that always crashes, instead of throwing a+                        -- Haskell error.+                        error "constrainValue{Case_}: nothing matched!"+                    Just GotStuck ->+                        constrainBranches v0 e bs+                    Just (Matched rho body) ->+                        pushes (toStatements rho) body (constrainValue v0)+            <|> constrainBranches v0 e bs++        _ :$ _ -> error "constrainValue: the impossible happened"+++-- | The default way of doing 'constrainValue' on a 'Case_' expression:+-- by constraining each branch. To do this we rely on the fact that+-- we're in a 'HMeasure' context (i.e., the continuation produces+-- programs of 'HMeasure' type). For each branch we first assert the+-- branch's pattern holds (via 'SGuard') and then call 'constrainValue'+-- on the body of the branch; and the final program is the superposition+-- of all these branches.+--+-- TODO: how can we avoid duplicating the scrutinee expression?+-- Would pushing a 'SLet' statement before the superpose be sufficient+-- to achieve maximal sharing?+constrainBranches+    :: (ABT Term abt)+    => abt '[] a+    -> abt '[] b+    -> [Branch b abt a]+    -> Dis abt ()+constrainBranches v0 e = choose . map constrainBranch+    where+    constrainBranch (Branch pat body) =+        let (vars,body') = caseBinds body+        in push (SGuard vars pat (Thunk e) []) body' (constrainValue v0)+++constrainDatum+    :: (ABT Term abt) => abt '[] a -> Datum (abt '[]) a -> Dis abt ()+constrainDatum v0 d =+    case patternOfDatum d of+    PatternOfDatum pat es -> do+        xs <- freshVars $ fmap11 (Hint Text.empty . typeOf) es+        emit_ $ \body ->+            syn $ Case_ v0+                [ Branch pat (binds_ xs body)+                , Branch PWild (P.reject $ (typeOf body))+                ]+        constrainValues xs es++constrainValues+    :: (ABT Term abt)+    => List1 Variable  xs+    -> List1 (abt '[]) xs+    -> Dis abt ()+constrainValues (Cons1 x xs) (Cons1 e es) =+    constrainValue (var x) e >> constrainValues xs es+constrainValues Nil1 Nil1 = return ()+constrainValues _ _ = error "constrainValues: the impossible happened"+++data PatternOfDatum (ast :: Hakaru -> *) (a :: Hakaru) =+    forall xs. PatternOfDatum+        !(Pattern xs a)+        !(List1 ast xs)++-- | Given a datum, return the pattern which will match it along+-- with the subexpressions which would be bound to patter-variables.+patternOfDatum :: Datum ast a -> PatternOfDatum ast a+patternOfDatum =+    \(Datum hint _typ d) ->+        podCode d $ \p es ->+        PatternOfDatum (PDatum hint p) es+    where+    podCode+        :: DatumCode xss ast a+        -> (forall bs. PDatumCode xss bs a -> List1 ast bs -> r)+        -> r+    podCode (Inr d) k = podCode   d $ \ p es -> k (PInr p) es+    podCode (Inl d) k = podStruct d $ \ p es -> k (PInl p) es++    podStruct+        :: DatumStruct xs ast a+        -> (forall bs. PDatumStruct xs bs a -> List1 ast bs -> r)+        -> r+    podStruct (Et d1 d2) k =+        podFun    d1 $ \p1 es1 ->+        podStruct d2 $ \p2 es2 ->+        k (PEt p1 p2) (es1 `append1` es2)+    podStruct Done k = k PDone Nil1++    podFun+        :: DatumFun x ast a+        -> (forall bs. PDatumFun x bs a -> List1 ast bs -> r)+        -> r+    podFun (Konst e) k = k (PKonst PVar) (Cons1 e Nil1)+    podFun (Ident e) k = k (PIdent PVar) (Cons1 e Nil1)+++----------------------------------------------------------------+-- | N.B., as with 'constrainValue', we assume that the first+-- argument is emissible. So it is the caller's responsibility to+-- ensure this (by calling 'atomize' as appropriate).+--+-- TODO: capture the emissibility requirement on the first argument+-- in the types.+constrainVariable+    :: (ABT Term abt) => abt '[] a -> Variable a -> Dis abt ()+constrainVariable v0 x =+    do locs <- getLocs+    -- If we get 'Nothing', then it turns out @x@ is a free variable.+    -- If @x@ is a free variable, then it's a neutral term; and we+    -- return 'bot' for neutral terms+       maybe bot lookForLoc (lookupAssoc x locs)+    where lookForLoc (Loc      l jxs) =+              let -- Assumption: js has no duplicates+                  permutes is js = length is == length js && +                                   Set.fromList is == Set.fromList (map indVar js)+              -- If we get 'Nothing', then it turns out @l@ is a free location.+              -- This is an error because of the invariant:+              --   if there exists an 'Assoc x ({Multi}Loc l _)' inside @locs@+              --   then there must be a statement on the 'ListContext' that binds @l@+              in (maybe (freeLocError l) return =<<) . select l $ \s ->+                  case s of+                    SBind l' e ixs -> do+                           Refl <- varEq l l'+                           guard (length ixs == length jxs) -- will error otherwise+                           Just $ do+                             inds <- getIndices+                             guard (jxs `permutes` inds) -- will bot otherwise+                             e' <- apply (zip ixs inds) (fromLazy e)+                             constrainOutcome v0 e'+                             unsafePush (SLet l (Whnf_ (Neutral v0)) inds)+                    SLet  l' e ixs -> do+                           Refl <- varEq l l'+                           guard (length ixs == length jxs) -- will error otherwise+                           Just $ do+                             inds <- getIndices+                             guard (jxs `permutes` inds) -- will bot otherwise+                             e' <- apply (zip ixs inds) (fromLazy e)+                             constrainValue v0 e'+                             unsafePush (SLet l (Whnf_ (Neutral v0)) inds)+                    SWeight _ _ -> Nothing+                    SGuard ls' pat scrutinee i -> error "TODO: constrainVariable{SGuard}"+          -- Case for MultiLoc+          lookForLoc (MultiLoc l jxs) = do+#ifdef __TRACE_DISINTEGRATE__+              traceM $ "looking for MultiLoc: " ++ show (prettyLoc (MultiLoc l jxs))+#endif       +              n    <- sizeInnermostInd l+              j    <- freshInd n+              x'   <- mkLoc Text.empty l (extendLocInds (indVar j) jxs)+              inds <- getIndices+              withIndices (extendIndices j inds) $+                          constrainValue (v0 P.! (var $ indVar j)) (var x')+                                            -- TODO use meta-index++----------------------------------------------------------------+-- | N.B., as with 'constrainValue', we assume that the first+-- argument is emissible. So it is the caller's responsibility to+-- ensure this (by calling 'atomize' as appropriate).+--+-- TODO: capture the emissibility requirement on the first argument+-- in the types.+constrainValueMeasureOp+    :: forall abt typs args a+    .  (ABT Term abt, typs ~ UnLCs args, args ~ LCs typs)+    => abt '[] ('HMeasure a)+    -> MeasureOp typs a+    -> SArgs abt args+    -> Dis abt ()+constrainValueMeasureOp v0 = go+    where+    -- TODO: for Lebesgue and Counting we use @bot@ because that's+    -- what the old finally-tagless code seems to have been doing.+    -- But is that right, or should they really be @return ()@?+    go :: MeasureOp typs a -> SArgs abt args -> Dis abt ()+    go Lebesgue    = \End               -> bot -- TODO: see note above+    go Counting    = \End               -> bot -- TODO: see note above+    go Categorical = \(e1 :* End)       ->+        constrainValue v0 (P.categorical e1)+    go Uniform     = \(e1 :* e2 :* End) ->+        constrainValue v0 (P.uniform' e1 e2)+    go Normal      = \(e1 :* e2 :* End) ->+        constrainValue v0 (P.normal'  e1 e2)+    go Poisson     = \(e1 :* End)       ->+        constrainValue v0 (P.poisson' e1)+    go Gamma       = \(e1 :* e2 :* End) ->+        constrainValue v0 (P.gamma'   e1 e2)+    go Beta        = \(e1 :* e2 :* End) ->+        constrainValue v0 (P.beta'    e1 e2)++----------------------------------------------------------------+-- | N.B., We assume that the first argument, @v0@, is already+-- atomized. So, this must be ensured before recursing, but we can+-- assume it's already been done by the IH.+--+-- N.B., we also rely on the fact that our 'HSemiring' instances+-- are actually all /commutative/ semirings. If that ever becomes+-- not the case, then we'll need to fix things here.+--+-- As written, this will do a lot of redundant work in atomizing+-- the subterms other than the one we choose to go backward on.+-- Because evaluation has side-effects on the heap and is heap+-- dependent, it seems like there may not be a way around that+-- issue. (I.e., we could use dynamic programming to efficiently+-- build up the 'M' computations, but not to evaluate them.) Of+-- course, really we shouldn't be relying on the structure of the+-- program here; really we should be looking at the heap-bound+-- variables in the term: choosing each @x@ to go backward on, treat+-- the term as a function of @x@, atomize that function (hence going+-- forward on the rest of the variables), and then invert it and+-- get the Jacobian.+--+-- TODO: find some way to capture in the type that the first argument+-- must be emissible.+constrainNaryOp+    :: (ABT Term abt)+    => abt '[] a+    -> NaryOp a+    -> Seq (abt '[] a)+    -> Dis abt ()+constrainNaryOp v0 o =+    case o of+    Sum theSemi ->+        lubSeq $ \es1 e es2 -> do+            u <- atomize $ syn (NaryOp_ (Sum theSemi) (es1 S.>< es2))+            v <- evaluate_ $ P.unsafeMinus_ theSemi v0 (fromWhnf u)+            constrainValue (fromWhnf v) e+    Prod theSemi ->+        lubSeq $ \es1 e es2 -> do+            u <- atomize $ syn (NaryOp_ (Prod theSemi) (es1 S.>< es2))+            let u' = fromWhnf u -- TODO: emitLet?+            emitWeight $ P.recip (toProb_abs theSemi u')+            v <- evaluate_ $ P.unsafeDiv_ theSemi v0 u'+            constrainValue (fromWhnf v) e+    Max theOrd ->+        chooseSeq $ \es1 e es2 -> do+            u <- atomize $ syn (NaryOp_ (Max theOrd) (es1 S.>< es2))+            emitGuard $ P.primOp2_ (Less theOrd) (fromWhnf u) v0+            constrainValue v0 e+    _ -> error $ "TODO: constrainNaryOp{" ++ show o ++ "}"+++-- TODO: if this function (or the component @toProb@ and @semiringAbs@+-- parts) turn out to be useful elsewhere, then we should move it+-- to the Prelude.+toProb_abs :: (ABT Term abt) => HSemiring a -> abt '[] a -> abt '[] 'HProb+toProb_abs HSemiring_Nat  = P.nat2prob+toProb_abs HSemiring_Int  = P.nat2prob . P.abs_+toProb_abs HSemiring_Prob = id+toProb_abs HSemiring_Real = P.abs_+++-- TODO: is there any way to optimise the zippering over the Seq, a la 'S.inits' or 'S.tails'?+-- TODO: really we want a dynamic programming approach to avoid unnecessary repetition of calling @evaluateNaryOp evaluate_@ on the two subsequences...+lubSeq :: (Alternative m) => (Seq a -> a -> Seq a -> m b) -> Seq a -> m b+lubSeq f = go S.empty+    where+    go xs ys =+        case S.viewl ys of+        S.EmptyL   -> empty+        y S.:< ys' -> f xs y ys' <|> go (xs S.|> y) ys'++chooseSeq :: (ABT Term abt)+          => (Seq a -> a -> Seq a -> Dis abt b)+          -> Seq a+          -> Dis abt b+chooseSeq f = choose  . go S.empty+    where+    go xs ys =+        case S.viewl ys of+        S.EmptyL   -> []+        y S.:< ys' -> f xs y ys' : go (xs S.|> y) ys'+++----------------------------------------------------------------+-- HACK: for a lot of these, we can't use the prelude functions+-- because Haskell can't figure out our polymorphism, so we have+-- to define our own versions for manually passing dictionaries+-- around.+--+-- | N.B., We assume that the first argument, @v0@, is already+-- atomized. So, this must be ensured before recursing, but we can+-- assume it's already been done by the IH.+--+-- TODO: find some way to capture in the type that the first argument+-- must be emissible.+constrainPrimOp+    :: forall abt typs args a+    .  (ABT Term abt, typs ~ UnLCs args, args ~ LCs typs)+    => abt '[] a+    -> PrimOp typs a+    -> SArgs abt args+    -> Dis abt ()+constrainPrimOp v0 = go+    where+    error_TODO op = error $ "TODO: constrainPrimOp{" ++ op ++"}"++    go :: PrimOp typs a -> SArgs abt args -> Dis abt ()+    go Not  = \(e1 :* End)       -> error_TODO "Not"+    go Impl = \(e1 :* e2 :* End) -> error_TODO "Impl"+    go Diff = \(e1 :* e2 :* End) -> error_TODO "Diff"+    go Nand = \(e1 :* e2 :* End) -> error_TODO "Nand"+    go Nor  = \(e1 :* e2 :* End) -> error_TODO "Nor"++    go Pi = \End -> bot -- because @dirac pi@ has no density wrt lebesgue++    go Sin = \(e1 :* End) -> do+        x0 <- emitLet' v0+        n  <- var <$> emitMBind P.counting+        let tau_n = P.real_ 2 P.* P.fromInt n P.* P.pi -- TODO: emitLet?+        emitGuard (P.negate P.one P.< x0 P.&& x0 P.< P.one)+        v  <- var <$> emitSuperpose+            [ P.dirac (tau_n P.+ P.asin x0)+            , P.dirac (tau_n P.+ P.pi P.- P.asin x0)+            ]+        emitWeight+            . P.recip+            . P.sqrt+            . P.unsafeProb+            $ (P.one P.- x0 P.^ P.nat_ 2)+        constrainValue v e1++    go Cos = \(e1 :* End) -> do+        x0 <- emitLet' v0+        n  <- var <$> emitMBind P.counting+        let tau_n = P.real_ 2 P.* P.fromInt n P.* P.pi+        emitGuard (P.negate P.one P.< x0 P.&& x0 P.< P.one)+        r  <- emitLet' (tau_n P.+ P.acos x0)+        v  <- var <$> emitSuperpose [P.dirac r, P.dirac (r P.+ P.pi)]+        emitWeight+            . P.recip+            . P.sqrt+            . P.unsafeProb+            $ (P.one P.- x0 P.^ P.nat_ 2)+        constrainValue v e1++    go Tan = \(e1 :* End) -> do+        x0 <- emitLet' v0+        n  <- var <$> emitMBind P.counting+        r  <- emitLet' (P.fromInt n P.* P.pi P.+ P.atan x0)+        emitWeight $ P.recip (P.one P.+ P.square x0)+        constrainValue r e1++    go Asin = \(e1 :* End) -> do+        x0 <- emitLet' v0+        emitWeight $ P.unsafeProb (P.cos x0)+        -- TODO: bounds check for -pi/2 <= v0 < pi/2+        constrainValue (P.sin x0) e1++    go Acos = \(e1 :* End) -> do+        x0 <- emitLet' v0+        emitWeight $ P.unsafeProb (P.sin x0)+        constrainValue (P.cos x0) e1++    go Atan = \(e1 :* End) -> do+        x0 <- emitLet' v0+        emitWeight $ P.recip (P.unsafeProb (P.cos x0 P.^ P.nat_ 2))+        constrainValue (P.tan x0) e1++    go Sinh      = \(e1 :* End)       -> error_TODO "Sinh"+    go Cosh      = \(e1 :* End)       -> error_TODO "Cosh"+    go Tanh      = \(e1 :* End)       -> error_TODO "Tanh"+    go Asinh     = \(e1 :* End)       -> error_TODO "Asinh"+    go Acosh     = \(e1 :* End)       -> error_TODO "Acosh"+    go Atanh     = \(e1 :* End)       -> error_TODO "Atanh"+    go RealPow   = \(e1 :* e2 :* End) ->+        -- TODO: There's a discrepancy between @(**)@ and @pow_@ in the old code...+        do+            -- TODO: if @v1@ is 0 or 1 then bot. Maybe the @log v1@ in @w@ takes care of the 0 case?+            u <- emitLet' v0+            -- either this from @(**)@:+            --   emitGuard  $ P.zero P.< u+            --   w <- atomize $ P.recip (P.abs (v0 P.* P.log v1))+            --   emitWeight $ P.unsafeProb (fromWhnf w)+            --   constrainValue (P.logBase v1 v0) e2+            -- or this from @pow_@:+            let w = P.recip (u P.* P.unsafeProb (P.abs (P.log e1)))+            emitWeight w+            constrainValue (P.log u P./ P.log e1) e2+            -- end.+        <|> do+            -- TODO: if @v2@ is 0 then bot. Maybe the weight @w@ takes care of this case?+            u <- emitLet' v0+            let ex = v0 P.** P.recip e2+            -- either this from @(**)@:+            --   emitGuard $ P.zero P.< u+            --   w <- atomize $ abs (ex / (v2 * v0))+            -- or this from @pow_@:+            let w = P.abs (P.fromProb ex P./ (e2 P.* P.fromProb u))+            -- end.+            emitWeight $ P.unsafeProb w+            constrainValue ex e1+    go Exp = \(e1 :* End) -> do+        x0 <- emitLet' v0+        -- TODO: do we still want\/need the @emitGuard (0 < x0)@ which is now equivalent to @emitGuard (0 /= x0)@ thanks to the types?+        emitWeight (P.recip x0)+        constrainValue (P.log x0) e1++    go Log = \(e1 :* End) -> do+        exp_x0 <- emitLet' (P.exp v0)+        emitWeight exp_x0+        constrainValue exp_x0 e1++    go (Infinity _)     = \End               -> error_TODO "Infinity" -- scalar0+    go GammaFunc        = \(e1 :* End)       -> error_TODO "GammaFunc" -- scalar1+    go BetaFunc         = \(e1 :* e2 :* End) -> error_TODO "BetaFunc" -- scalar2+    go (Equal  theOrd)  = \(e1 :* e2 :* End) -> error_TODO "Equal"+    go (Less   theOrd)  = \(e1 :* e2 :* End) -> error_TODO "Less"+    go (NatPow theSemi) = \(e1 :* e2 :* End) -> error_TODO "NatPow"+    go (Negate theRing) = \(e1 :* End) ->+        -- TODO: figure out how to merge this implementation of @rr1 negate@ with the one in 'evaluatePrimOp' to DRY+        -- TODO: just emitLet the @v0@ and pass the neutral term to the recursive call?+        let negate_v0 = syn (PrimOp_ (Negate theRing) :$ v0 :* End)+                -- case v0 of+                -- Neutral e ->+                --     Neutral $ syn (PrimOp_ (Negate theRing) :$ e :* End)+                -- Head_ v ->+                --     case theRing of+                --     HRing_Int  -> Head_ . reflect . negate $ reify v+                --     HRing_Real -> Head_ . reflect . negate $ reify v+        in constrainValue negate_v0 e1++    go (Abs theRing) = \(e1 :* End) -> do+        let theSemi = hSemiring_HRing theRing+            theOrd  =+                case theRing of+                HRing_Int  -> HOrd_Int+                HRing_Real -> HOrd_Real+            theEq   = hEq_HOrd theOrd+            signed  = C.singletonCoercion (C.Signed theRing)+            zero    = P.zero_ theSemi+            lt      = P.primOp2_ $ Less   theOrd+            eq      = P.primOp2_ $ Equal  theEq+            neg     = P.primOp1_ $ Negate theRing++        x0 <- emitLet' (P.coerceTo_ signed v0)+        v  <- var <$> emitMBind+            (P.if_ (lt zero x0)+                (P.dirac x0 P.<|> P.dirac (neg x0))+                (P.if_ (eq zero x0)+                    (P.dirac zero)+                    (P.reject . SMeasure $ typeOf zero)))+        constrainValue v e1++    go (Signum theRing) = \(e1 :* End) ->+        case theRing of+        HRing_Real -> bot+        HRing_Int  -> do+            x <- var <$> emitMBind P.counting+            emitGuard $ P.signum x P.== v0+            constrainValue x e1++    go (Recip theFractional) = \(e1 :* End) -> do+        x0 <- emitLet' v0+        emitWeight+            . P.recip+            . P.unsafeProbFraction_ theFractional+            -- TODO: define a dictionary-passing variant of 'P.square' instead, to include the coercion in there explicitly...+            $ square (hSemiring_HFractional theFractional) x0+        constrainValue (P.primOp1_ (Recip theFractional) x0) e1++    go (NatRoot theRadical) = \(e1 :* e2 :* End) ->+        case theRadical of+        HRadical_Prob -> do+            x0 <- emitLet' v0+            u2 <- fromWhnf <$> atomize e2+            emitWeight (P.nat2prob u2 P.* x0)+            constrainValue (x0 P.^ u2) e1++    go (Erf theContinuous) = \(e1 :* End) ->+        error "TODO: constrainPrimOp: need InvErf to disintegrate Erf"+++-- HACK: can't use @(P.^)@ because Haskell can't figure out our polymorphism+square :: (ABT Term abt) => HSemiring a -> abt '[] a -> abt '[] a+square theSemiring e =+    syn (PrimOp_ (NatPow theSemiring) :$ e :* P.nat_ 2 :* End)+++----------------------------------------------------------------+----------------------------------------------------------------+-- TODO: do we really want the first argument to be a term at all,+-- or do we want something more general like patters for capturing+-- measurable events?+--+-- | This is a helper function for 'constrainValue' to handle 'SBind'+-- statements (just as the 'perform' argument to 'evaluate' is a+-- helper for handling 'SBind' statements).+--+-- N.B., We assume that the first argument, @v0@, is already+-- atomized. So, this must be ensured before recursing, but we can+-- assume it's already been done by the IH. Technically, we con't+-- care whether the first argument is in normal form or not, just+-- so long as it doesn't contain any heap-bound variables.+--+-- This is the function called @(<<|)@ in the paper, though notably+-- we swap the argument order.+--+-- TODO: find some way to capture in the type that the first argument+-- must be emissible, to help avoid accidentally passing the arguments+-- in the wrong order!+--+-- TODO: under what circumstances is @constrainOutcome x m@ different+-- from @constrainValue x =<< perform m@? If they're always the+-- same, then we should just use that as the definition in order+-- to avoid repeating ourselves+constrainOutcome+    :: forall abt a+    .  (ABT Term abt)+    => abt '[] a+    -> abt '[] ('HMeasure a)+    -> Dis abt ()+constrainOutcome v0 e0 =+#ifdef __TRACE_DISINTEGRATE__+    getLocs >>= \locs ->+    getIndices >>= \inds ->+    trace (+        let s = "-- constrainOutcome"+        in "\n" ++ s ++ ": "+            ++ show (pretty v0)+            ++ "\n" ++ replicate (length s) ' ' ++ ": "+            ++ show (pretty e0) ++ "\n"+            ++ "at " ++  show (ppInds inds) ++ "\n"+            ++ show (prettyLocs locs)+          ) $+#endif+    do  w0 <- evaluate_ e0+        case w0 of+            Neutral _ -> bot+            Head_   v -> go v+    where+    impossible = error "constrainOutcome: the impossible happened"++    go :: Head abt ('HMeasure a) -> Dis abt ()+    go (WLiteral _)          = impossible+    -- go (WDatum _)         = impossible+    -- go (WEmpty _)         = impossible+    -- go (WArray _ _)       = impossible+    -- go (WLam _)           = impossible+    -- go (WIntegrate _ _ _) = impossible+    -- go (WSummate   _ _ _) = impossible+    go (WCoerceTo   _ _)     = impossible+    go (WUnsafeFrom _ _)     = impossible+    go (WMeasureOp o es)     = constrainOutcomeMeasureOp v0 o es+    go (WDirac e1)           = constrainValue v0 e1+    go (WMBind e1 e2)        =+        caseBind e2 $ \x e2' -> do+            i <- getIndices+            push (SBind x (Thunk e1) i) e2' (constrainOutcome v0)+    go (WPlate e1 e2)        = do+        x' <- pushPlate e1 e2+        constrainValue v0 (var x')++    go (WChain e1 e2 e3)     = error "TODO: constrainOutcome{Chain}"+    go (WReject typ)         = emit_ $ \m -> P.reject (typeOf m)+    go (WSuperpose pes) = do+        i <- getIndices+        if not (null i) && L.length pes > 1 then bot else+          emitFork_ (P.superpose . fmap ((,) P.one))+                    (fmap (\(p,e) -> push (SWeight (Thunk p) i) e (constrainOutcome v0))+                          pes)++-- TODO: should this really be different from 'constrainValueMeasureOp'?+--+-- TODO: find some way to capture in the type that the first argument+-- must be emissible.+constrainOutcomeMeasureOp+    :: (ABT Term abt, typs ~ UnLCs args, args ~ LCs typs)+    => abt '[] a+    -> MeasureOp typs a+    -> SArgs abt args+    -> Dis abt ()+constrainOutcomeMeasureOp v0 = go+    where+    -- Per the paper+    go Lebesgue = \End -> return ()++    -- TODO: I think, based on Hakaru v0.2.0+    go Counting = \End -> return ()++    go Categorical = \(e1 :* End) -> do+        -- TODO: check that v0' is < then length of e1+        pushWeight (P.densityCategorical e1 v0)++    -- Per the paper+    go Uniform = \(lo :* hi :* End) -> do+        v0' <- emitLet' v0+        pushGuard (lo P.<= v0' P.&& v0' P.<= hi)+        pushWeight (P.densityUniform lo hi v0')++    -- TODO: Add fallback handling of Normal that does not atomize mu,sd.+    -- This fallback is as if Normal were defined in terms of Lebesgue+    -- and a density Weight.  This fallback is present in Hakaru v0.2.0+    -- in order to disintegrate a program such as+    --  x <~ normal(0,1)+    --  y <~ normal(x,1)+    --  return ((x+(y+y),x)::pair(real,real))+    go Normal = \(mu :* sd :* End) -> do+        -- N.B., if\/when extending this to higher dimensions, the real equation is @recip (sqrt (2*pi*sd^2) ^ n) * exp (negate (norm_n (v0 - mu) ^ 2) / (2*sd^2))@ for @Real^n@.+        pushWeight (P.densityNormal mu sd v0)++    go Poisson = \(e1 :* End) -> do+        v0' <- emitLet' v0+        pushGuard (P.nat_ 0 P.<= v0' P.&& P.prob_ 0 P.< e1)+        pushWeight (P.densityPoisson e1 v0')++    go Gamma = \(e1 :* e2 :* End) -> do+        v0' <- emitLet' v0+        pushGuard (P.prob_ 0 P.< v0' P.&&+                   P.prob_ 0 P.< e1  P.&&+                   P.prob_ 0 P.< e2)+        pushWeight (P.densityGamma e1 e2 v0')+    go Beta = \(e1 :* e2 :* End) -> do+        v0' <- emitLet' v0+        pushGuard (P.prob_ 0 P.<= v0' P.&&+                   P.prob_ 1 P.>= v0' P.&&+                   P.prob_ 0 P.< e1   P.&&+                   P.prob_ 0 P.< e2)+        pushWeight (P.densityBeta e1 e2 v0')++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Evaluation/Coalesce.hs view
@@ -0,0 +1,73 @@+{-# LANGUAGE DataKinds+           , GADTs+           , Rank2Types+           , FlexibleContexts+           #-}++----------------------------------------------------------------+--                                                    2016.07.19+-- |+-- Module      :  Language.Hakaru.Evaluation.Coalesce+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  zsulliva@indiana.edu+-- Stability   :  experimental+-- Portability :  GHC-only+--+----------------------------------------------------------------++module Language.Hakaru.Evaluation.Coalesce+  ( coalesce )+  where++import qualified Language.Hakaru.Parser.AST as U+import           Language.Hakaru.Syntax.ABT+import qualified Data.Foldable              as F++import Language.Hakaru.Syntax.IClasses++coalesce+    :: U.AST+    -> U.AST+coalesce =+    cataABT_ alg+    where+    alg :: forall abt a. (ABT U.Term abt) => U.Term abt a -> abt '[] a+    alg (U.NaryOp_ op args) = syn $ U.NaryOp_ op (coalesceNaryOp op args)+    alg t                   = syn t++coalesceNaryOp+    :: (ABT U.Term abt)+    => U.NaryOp+    -> [abt '[] a]+    -> [abt '[] a]+coalesceNaryOp op = F.concatMap $ \ast' ->+     caseVarSyn ast' (return . var) $ \t ->+       case t of+       U.NaryOp_ op' args' | op == op' -> coalesceNaryOp op args'+       _                               -> [ast']+++type M  = MetaABT U.SourceSpan U.Term++preserveMetadata+   :: (M xs a -> M xs a)+   -> M xs a+   -> M xs a+preserveMetadata f x =+    case getMetadata x of+      Nothing -> f x+      Just s  -> withMetadata s (f x)++cataABT_+    :: (forall    a. U.Term M a -> M '[] a)+    -> (forall xs a. M xs a     -> M xs  a)+cataABT_ syn_ = start+    where+    start :: forall xs a. M xs a -> M xs a+    start = preserveMetadata (loop . viewABT)++    loop ::  forall xs a. View (U.Term M) xs a -> M xs a+    loop (Syn  t)   = syn_  (fmap21 start t)+    loop (Var  x)   = var  x+    loop (Bind x e) = bind x (loop e)
+ haskell/Language/Hakaru/Evaluation/ConstantPropagation.hs view
@@ -0,0 +1,68 @@+{-# LANGUAGE CPP+           , GADTs+           , DataKinds+           , Rank2Types+           , ScopedTypeVariables+           , MultiParamTypeClasses+           , FlexibleContexts+           , FlexibleInstances+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.04.02+-- |+-- Module      :  Language.Hakaru.Evaluation.ConstantPropagation+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+--+----------------------------------------------------------------+module Language.Hakaru.Evaluation.ConstantPropagation+    ( constantPropagation+    ) where++#if __GLASGOW_HASKELL__ < 710+import           Data.Functor         ((<$>))+import           Control.Applicative  (Applicative(..))+#endif++import Language.Hakaru.Syntax.IClasses (Traversable21(..))+import Language.Hakaru.Syntax.ABT      (View(..), ABT(..), cataABT)+import Language.Hakaru.Syntax.AST+import Language.Hakaru.Evaluation.EvalMonad (runPureEvaluate)++----------------------------------------------------------------+----------------------------------------------------------------+-- TODO: try evaluating certain things even if not all their immediate+-- subterms are literals. For example:+-- (1) substitute let-bindings of literals+-- (2) evaluate beta-redexes where the argument is a literal+-- (3) evaluate case-of-constructor if we can+-- (4) handle identity elements for NaryOps+-- N.B., some of these will require performing top-down work to+-- avoid re-traversing subtrees.+--+-- | Perform basic constant propagation.+constantPropagation+    :: forall abt a. (ABT Term abt) => abt '[] a -> abt '[] a+constantPropagation =+    cataABT var bind alg+    where+    getLiteral :: forall xs b. abt xs b -> Maybe (abt xs b)+    getLiteral e =+        case viewABT e of+        Syn (Literal_ _) -> Just e+        _                -> Nothing++    alg :: forall b. Term abt b -> abt '[] b+    alg t =+        case traverse21 getLiteral t of+        Nothing -> syn t+        Just t' -> runPureEvaluate (syn t')++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Evaluation/DisintegrationMonad.hs view
@@ -0,0 +1,910 @@+{-# LANGUAGE CPP+           , GADTs+           , KindSignatures+           , DataKinds+           , PolyKinds+           , TypeOperators+           , Rank2Types+           , FlexibleContexts+           , MultiParamTypeClasses+           , FlexibleInstances+           , UndecidableInstances+           , EmptyCase+           , ScopedTypeVariables+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.05.24+-- |+-- Module      :  Language.Hakaru.Evaluation.DisintegrationMonad+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- The 'EvaluationMonad' for "Language.Hakaru.Disintegrate"+----------------------------------------------------------------+module Language.Hakaru.Evaluation.DisintegrationMonad+    (+    -- * The disintegration monad+    -- ** List-based version+      getStatements, putStatements+    , ListContext(..), Ans, Dis(..), runDis+    -- ** TODO: IntMap-based version+    +    -- * Operators on the disintegration monad+    -- ** The \"zero\" and \"one\"+    , bot+    --, reject+    -- ** Emitting code+    , emit+    , emitMBind+    , emitLet+    , emitLet'+    , emitUnpair+    -- TODO: emitUneither+    -- emitCaseWith+    , emit_+    , emitMBind_+    , emitGuard+    , emitWeight+    , emitFork_+    , emitSuperpose+    , choose+    -- * Overrides for original in Evaluation.Types+    , pushPlate+    -- * For Arrays/Plate+    , getIndices+    , withIndices+    , extendIndices+    , extendLocInds+    , statementInds+    , sizeInnermostInd+    -- * Locs+    , Loc(..)+    , getLocs+    , putLocs+    , insertLoc+    , adjustLoc+    , mkLoc+    , freeLocError+    , apply+#ifdef __TRACE_DISINTEGRATE__+    , prettyLoc+    , prettyLocs+#endif    +    ) where++import           Prelude              hiding (id, (.))+import           Control.Category     (Category(..))+#if __GLASGOW_HASKELL__ < 710+import           Data.Monoid          (Monoid(..))+import           Data.Functor         ((<$>))+import           Control.Applicative  (Applicative(..))+#endif+import           Data.Maybe+import qualified Data.Foldable        as F+import qualified Data.Traversable     as T+import           Data.List.NonEmpty   (NonEmpty(..))+import qualified Data.List.NonEmpty   as NE+import           Control.Applicative  (Alternative(..))+import           Control.Monad        (MonadPlus(..),foldM,guard)+import           Data.Text            (Text)+import qualified Data.Text            as Text+import           Data.Number.Nat++import Language.Hakaru.Syntax.IClasses+import Language.Hakaru.Types.DataKind+import Language.Hakaru.Types.Sing    (Sing(..), sUnMeasure, sUnPair, sUnit)+import Language.Hakaru.Syntax.AST+import Language.Hakaru.Syntax.Datum+import Language.Hakaru.Syntax.DatumABT+import Language.Hakaru.Syntax.TypeOf+import Language.Hakaru.Syntax.ABT+import qualified Language.Hakaru.Syntax.Prelude as P+import Language.Hakaru.Evaluation.Types+import Language.Hakaru.Evaluation.PEvalMonad (ListContext(..))+import Language.Hakaru.Evaluation.Lazy (reifyPair)    ++#ifdef __TRACE_DISINTEGRATE__+import Debug.Trace (trace, traceM)+import qualified Text.PrettyPrint     as PP+import Language.Hakaru.Pretty.Haskell (ppVariable, pretty)+#endif++getStatements :: Dis abt [Statement abt 'Impure]+getStatements = Dis $ \_ c h -> c (statements h) h++putStatements :: [Statement abt 'Impure] -> Dis abt ()+putStatements ss =+    Dis $ \_ c (ListContext i _) loc ->+        c () (ListContext i ss) loc++----------------------------------------------------------------+----------------------------------------------------------------++-- | Capturing substitution: +plug :: forall abt a xs b+     .  (ABT Term abt)+     => Variable a+     -> abt '[] a+     -> abt xs b+     -> abt xs b+plug x e = start+    where+      start :: forall xs' b' . abt xs' b' -> abt xs' b'+      start f = loop f (viewABT f)+      loop :: forall xs' b'. abt xs' b' -> View (Term abt) xs' b' -> abt xs' b'+      loop _ (Syn t) = syn $! fmap21 start t+      loop f (Var z) = case varEq x z of+                       Just Refl -> e+                       Nothing   -> f+      loop f (Bind _ _) = caseBind f $ \z f' -> +                          bind z (loop f' (viewABT f'))++-- | Perform multiple capturing substitutions+plugs :: forall abt xs a+      .  (ABT Term abt)+      => Assocs (abt '[]) +      -> abt xs a+      -> abt xs a+plugs rho0 e0 = F.foldl (\e (Assoc x v) -> plug x v e) e0 (unAssocs rho0)++-- | Plug a term into a context. That is, the 'statements' of the+-- context specifies a program with a hole in it; so we plug the+-- given term into that hole, returning the complete program.+residualizeListContext+    :: forall abt a+    .  (ABT Term abt)+    => ListContext abt 'Impure+    -> Assocs (abt '[])+    -> abt '[] ('HMeasure a)+    -> abt '[] ('HMeasure a)+residualizeListContext ss rho e0 =+    -- N.B., we use a left fold because the head of the list of+    -- statements is the one closest to the hole.+#ifdef __TRACE_DISINTEGRATE__+    trace ("e0: " ++ show (pretty e0) ++ "\n"+          ++ show (pretty_Statements (statements ss))) $+#endif+    foldl step (plugs rho e0) (statements ss)+    where    +    step+        :: abt '[] ('HMeasure a)+        -> Statement abt 'Impure+        -> abt '[] ('HMeasure a)+    step e s =        +#ifdef __TRACE_DISINTEGRATE__+        trace ("wrapping " ++ show (ppStatement 0 s) ++ "\n"+               ++ "around term " ++ show (pretty e)) $+#endif  +        case s of       +        SBind x body _ ->+            -- TODO: if @body@ is dirac, then treat as 'SLet'+            syn (MBind :$ plugs rho (fromLazy body) :* bind x e :* End)+        SLet x body _+            | not (x `memberVarSet` freeVars e) ->+#ifdef __TRACE_DISINTEGRATE__+               trace ("could not find location" ++ show x ++ "\n"+                     ++ "in term " ++ show (pretty e) ++ "\n"+                     ++ "given rho " ++ show (prettyAssocs rho)) $+#endif                +                e+            -- TODO: if used exactly once in @e@, then inline.+            | otherwise ->+                case getLazyVariable body of+                Just y  -> plug x (plugs rho (var y)) e+                Nothing ->+                    case getLazyLiteral body of+                    Just v  -> plug x (syn $ Literal_ v) e+                    Nothing ->+                        syn (Let_ :$ plugs rho (fromLazy body) :* bind x e :* End)+        SGuard xs pat scrutinee _ ->+            syn $ Case_ (plugs rho $ fromLazy scrutinee)+                [ Branch pat   (binds_ xs e)+                , Branch PWild (P.reject $ typeOf e)+                ]+        SWeight body _ -> syn $ Superpose_ ((plugs rho $ fromLazy body, e) :| [])++----------------------------------------------------------------+-- A location is a variable *use* instantiated at some list of indices.+data Loc :: (Hakaru -> *) -> Hakaru -> * where+     Loc :: Variable a +         -> [Variable 'HNat]+         -> Loc ast a+     MultiLoc+         :: Variable a+         -> [Variable 'HNat]+         -> Loc ast ('HArray a)++locIndices :: Loc ast a -> [Variable 'HNat]+locIndices (Loc       _ inds) = inds+locIndices (MultiLoc  _ inds) = inds++extendLocInds :: Variable 'HNat -> [Variable 'HNat] -> [Variable 'HNat]+extendLocInds = (:)++#ifdef __TRACE_DISINTEGRATE__+      +prettyLoc :: Loc ast (a :: Hakaru) -> PP.Doc+prettyLoc (Loc l inds)      = PP.text "Loc" PP.<+> ppVariable l+                              PP.<+> ppList (map ppVariable inds)+prettyLoc (MultiLoc l inds) = PP.text "MultiLoc" PP.<+> ppVariable l+                              PP.<+> ppList (map ppVariable inds)++prettyLocs :: (ABT Term abt)+           => Assocs (Loc (abt '[]))+           -> PP.Doc+prettyLocs a = PP.vcat $ map go (fromAssocs a)+  where go (Assoc x l) = ppVariable x PP.<+>+                         PP.text "->" PP.<+>+                         prettyLoc l++#endif                           ++-- In the paper we say that result must be a 'Whnf'; however, in+-- the paper it's also always @HMeasure a@ and everything of that+-- type is a WHNF (via 'WMeasure') so that's a trivial statement+-- to make. If we turn it back into some sort of normal form, then+-- it must be one preserved by 'residualizeContext'.+--+-- Also, we add the list in order to support "lub" without it living in the AST.+-- TODO: really we should use LogicT...+type Ans abt a+  =  ListContext abt 'Impure+  -> Assocs (Loc (abt '[]))+  -> [abt '[] ('HMeasure a)]+++----------------------------------------------------------------+-- TODO: defunctionalize the continuation. In particular, the only+-- heap modifications we need are 'push' and a variant of 'update'+-- for finding\/replacing a binding once we have the value in hand;+-- and the only 'freshNat' modifications are to allocate new 'Nat'.+-- We could defunctionalize the second arrow too by relying on the+-- @Codensity (ReaderT e m) ~= StateT e (Codensity m)@ isomorphism,+-- which makes explicit that the only thing other than 'ListContext'+-- updates is emitting something like @[Statement]@ to serve as the+-- beginning of the final result.+--+-- TODO: give this a better, more informative name!+--+-- N.B., This monad is used not only for both 'perform' and 'constrainOutcome', but also for 'constrainValue'.+newtype Dis abt x =+    Dis { unDis :: forall a. [Index (abt '[])] -> (x -> Ans abt a) -> Ans abt a }+    -- == @Codensity (Ans abt)@, assuming 'Codensity' is poly-kinded like it should be+    -- If we don't want to allow continuations that can make nondeterministic choices, then we should use the right Kan extension itself, rather than the Codensity specialization of it.+++-- | Run a computation in the 'Dis' monad, residualizing out all the+-- statements in the final evaluation context. The second argument+-- should include all the terms altered by the 'Dis' expression; this+-- is necessary to ensure proper hygiene; for example(s):+--+-- > runDis (perform e) [Some2 e]+-- > runDis (constrainOutcome e v) [Some2 e, Some2 v]+--+-- We use 'Some2' on the inputs because it doesn't matter what their+-- type or locally-bound variables are, so we want to allow @f@ to+-- contain terms with different indices.+runDis :: (ABT Term abt, F.Foldable f)+    => Dis abt (abt '[] a)+    -> f (Some2 abt)+    -> [abt '[] ('HMeasure a)]+runDis d es =+    m0 [] c0 (ListContext i0 []) emptyAssocs+    where+    (Dis m0) = d >>= residualizeLocs+    -- TODO: we only use dirac because 'residualizeListContext' requires it to already be a measure; unfortunately this can result in an extraneous @(>>= \x -> dirac x)@ redex at the end of the program. In principle, we should be able to eliminate that redex by changing the type of 'residualizeListContext'...+    c0 (e,rho) ss _ = [residualizeListContext ss rho (syn(Dirac :$ e :* End))]+                  +    i0 = maxNextFree es++{---------------------------------------------------------------------------------- + + residualizeLocs does the following:+ 1. update the heap by constructing plate/array around statements with nonempty indices+ 2. use locations to construct terms out of var and "!" (for indexing into arrays)++For example, consider the state:++  list context (aka heap) =+  l1 <- lebesgue []+  l2 <- plate (normal 0 1) []+  l3 <- lebesgue [i]+  l4 <- dirac x3 []+  l5 <- normal 0 1 [j]+  +  assocs (aka locs) =+  x1 -> Loc l1 []+  x2 -> Loc l2 []+  x3 -> MultiLoc l3 []+  x4 -> Loc l4 []+  x5 -> Loc l5 [k]+  +Here the types of the above variables are:++  l1, x1 :: Real+  l2, x2 :: Array Real+  l3 :: Real+  x3 :: Array Real+  l4, x4 :: Array Real+  l5, x5 :: Real++Then residualizeLoc does two things:++1.Change the heap++  list context = +  l1' <- lebesgue []+  l2' <- plate (normal 0 1) []+  l3' <- plate i (lebesgue)+  l4' <- dirac x3+  l5' <- plate j (normal 0 1)++2.Create new association table++  rho = +  x1 -> var l1'+  x2 -> var l2'+  x3 -> array i' (l3' ! i')+  x4 -> var l4'+  x5 -> var l5' ! k ++----------------------------------------------------------------------------------}+residualizeLocs :: forall a abt. (ABT Term abt)+                => abt '[] a+                -> Dis abt (abt '[] a, Assocs (abt '[]))+residualizeLocs e = do+  ss <- getStatements+  (ss', newlocs) <- foldM step ([], emptyAssocs) ss+  rho <- convertLocs newlocs+  putStatements (reverse ss')+#ifdef __TRACE_DISINTEGRATE__+  trace ("residualizeLocs: old heap:\n" ++ show (pretty_Statements ss )) $ return ()+  trace ("residualizeLocs: new heap:\n" ++ show (pretty_Statements ss')) $ return ()+  locs <- getLocs+  traceM ("oldlocs:\n" ++ show (prettyLocs locs) ++ "\n")+  traceM ("new assoc for renaming:\n" ++ show (prettyAssocs rho))+#endif+  return (e, rho)+    where step (ss',newlocs) s = do (s',newlocs') <- residualizeLoc s+                                    return (s':ss', insertAssocs newlocs' newlocs)++data Name (a :: Hakaru) = Name {nameHint :: Text, nameID :: Nat}++varName :: Variable a -> Name b+varName x = Name (varHint x) (varID x)++residualizeLoc :: (ABT Term abt)+               => Statement abt 'Impure+               -> Dis abt (Statement abt 'Impure, Assocs Name)+residualizeLoc s =+    case s of+      SBind l _ _ -> do +             (s', newname) <- reifyStatement s+             return (s', singletonAssocs l newname)+      SLet  l _ _ -> do+             (s', newname) <- reifyStatement s+             return (s', singletonAssocs l newname)+      SWeight w inds    -> do+             l <- freshVar Text.empty sUnit+             let bodyW = Thunk $ P.weight (fromLazy w)+             (s', newname) <- reifyStatement (SBind l bodyW inds)+             return (s', singletonAssocs l newname)+      SGuard ls _ _ ixs+        | null ixs  -> return (s, toAssocs1 ls (fmap11 varName ls))+        | otherwise -> error "undefined: case statement under an array"++reifyStatement :: (ABT Term abt)+               => Statement abt 'Impure+               -> Dis abt (Statement abt 'Impure, Name a)+reifyStatement s =+    case s of+      SBind l _    []     -> return (s, varName l)+      SBind l body (i:is) -> do+        let plate = Thunk . P.plateWithVar (indSize i) (indVar i)+        l' <- freshVar (varHint l) (SArray (varType l))+        reifyStatement (SBind l' (plate $ fromLazy body) is)+      SLet  l _    []     -> return (s, varName l)+      SLet  l body (i:is) -> do+        let array = Thunk . P.arrayWithVar (indSize i) (indVar i)+        l' <- freshVar (varHint l) (SArray (varType l))+        reifyStatement (SLet  l' (array $ fromLazy body) is)+      SWeight _    _      -> error "reifyStatement called on SWeight"+      SGuard _ _ _ _      -> error "reifyStatement called on SGuard"+                             +sizeInnermostInd :: (ABT Term abt)+                 => Variable (a :: Hakaru)+                 -> Dis abt (abt '[] 'HNat)+sizeInnermostInd l =+    (maybe (freeLocError l) return =<<) . select l $ \s ->+        do guard (length (statementInds s) >= 1)+           case s of+             SBind l' _ ixs -> do Refl <- varEq l l'+                                  Just $ unsafePush s >>+                                         return (indSize (head ixs))+             SLet  l' _ ixs -> do Refl <- varEq l l'+                                  Just $ unsafePush s >>+                                         return (indSize (head ixs))+             SWeight _ _    -> Nothing+             SGuard _ _ _ _ -> error "TODO: sizeInnermostInd{SGuard}"+                                         +fromLoc :: (ABT Term abt)+        => Name b+        -> Sing a+        -> [Variable 'HNat]+        -> abt '[] a+fromLoc name typ []     = var $ Variable { varHint = nameHint name+                                         , varID   = nameID name+                                         , varType = typ }+fromLoc name typ (i:is) = fromLoc name (SArray typ) is P.! var i+                     +convertLocs :: (ABT Term abt)+            => Assocs Name+            -> Dis abt (Assocs (abt '[]))+convertLocs newlocs = F.foldr step emptyAssocs . fromAssocs <$> getLocs+    where+      build :: (ABT Term abt)+            => Assoc (Loc (abt '[]))+            -> Name a+            -> Assoc (abt '[])+      build (Assoc x loc) name =+          Assoc x (fromLoc name (varType x)+                    (case loc of Loc _ js -> js; MultiLoc _ js -> js))+      step assoc@(Assoc _ loc) = insertAssoc $+          case loc of+                 Loc      l _ -> maybe (freeLocError l)+                                       (build assoc)+                                       (lookupAssoc l newlocs)+                 MultiLoc l _ -> maybe (freeLocError l)+                                       (build assoc)+                                       (lookupAssoc l newlocs)++freeLocError :: Variable (a :: Hakaru) -> b+freeLocError l = error $ "Found a free location " ++ show l++apply :: (ABT Term abt)+      => [(Index (abt '[]), Index (abt '[]))]+      -> abt '[] a+      -> Dis abt (abt '[] a)+apply ijs e = do locs <- fromAssocs <$> getLocs+                 rho' <- foldM step rho locs+                 return (renames rho' e)+    where+      rho = toAssocs $ map (\(i,j) -> Assoc (indVar i) (indVar j)) ijs+      step r (Assoc x loc) =+            let inds  = locIndices loc+                check i = lookupAssoc i rho+                inds' = map (\i -> fromMaybe i (check i)) inds+            in if (any isJust (map check inds))+               then do x' <- case loc of+                               Loc      l _ -> mkLoc      Text.empty l inds'+                               MultiLoc l _ -> mkMultiLoc Text.empty l inds'+                       return (insertAssoc (Assoc x x') r)+               else return r+                           +extendIndices+    :: (ABT Term abt)+    => Index (abt '[])+    -> [Index (abt '[])]+    -> [Index (abt '[])]+-- TODO: check all Indices are unique+extendIndices j js | j `elem` js+                   = error ("Duplicate index between " )+                     -- TODO finish this error message by+                     -- defining Show for Index+                   | otherwise+                   = j : js++-- give better name+statementInds :: Statement abt p -> [Index (abt '[])]+statementInds (SBind   _ _   i) = i+statementInds (SLet    _ _   i) = i+statementInds (SWeight _     i) = i+statementInds (SGuard  _ _ _ i) = i+statementInds (SStuff0 _     i) = i+statementInds (SStuff1 _ _   i) = i++getLocs :: (ABT Term abt)+        => Dis abt (Assocs (Loc (abt '[])))+getLocs = Dis $ \_ c h l -> c l h l++putLocs :: (ABT Term abt)+        => Assocs (Loc (abt '[]))+        -> Dis abt ()+putLocs l = Dis $ \_ c h _ -> c () h l++insertLoc :: (ABT Term abt)+          => Variable a+          -> Loc (abt '[]) a+          -> Dis abt ()+insertLoc v loc = +  Dis $ \_ c h l -> c () h $+    insertAssoc (Assoc v loc) l++adjustLoc :: (ABT Term abt)+          => Variable (a :: Hakaru)+          -> (Assoc (Loc (abt '[])) -> Assoc (Loc (abt '[])))+          -> Dis abt ()+adjustLoc x f = do+    locs <- getLocs+    putLocs $ adjustAssoc x f locs++mkLoc+    :: (ABT Term abt)+    => Text+    -> Variable (a :: Hakaru)+    -> [Variable 'HNat]+    -> Dis abt (Variable a)+mkLoc hint s inds = do+  x <- freshVar hint (varType s)+  insertLoc x (Loc s inds)+  return x++mkLocs+    :: (ABT Term abt)+    => List1 Variable (xs :: [Hakaru])+    -> [Variable 'HNat]+    -> Dis abt (List1 Variable xs)+mkLocs Nil1         _    = return Nil1+mkLocs (Cons1 x xs) inds = Cons1+                           <$> mkLoc Text.empty x inds+                           <*> mkLocs xs inds++mkMultiLoc+    :: (ABT Term abt)+    => Text+    -> Variable a+    -> [Variable 'HNat]+    -> Dis abt (Variable ('HArray a))+mkMultiLoc hint s inds = do+  x' <- freshVar hint (SArray $ varType s)+  insertLoc x' (MultiLoc s inds)+  return x'++instance Functor (Dis abt) where+    fmap f (Dis m)  = Dis $ \i c -> m i (c . f)++instance Applicative (Dis abt) where+    pure x            = Dis $ \_ c -> c x+    Dis mf <*> Dis mx = Dis $ \i c -> mf i $ \f -> mx i $ \x -> c (f x)++instance Monad (Dis abt) where+    return      = pure+    Dis m >>= k = Dis $ \i c -> m i $ \x -> unDis (k x) i c++instance Alternative (Dis abt) where+    empty           = Dis $ \_ _ _ _ -> []+    Dis m <|> Dis n = Dis $ \i c h l -> m i c h l ++ n i c h l++instance MonadPlus (Dis abt) where+    mzero = empty -- aka "bot"+    mplus = (<|>) -- aka "lub"++instance (ABT Term abt) => EvaluationMonad abt (Dis abt) 'Impure where+    freshNat =+        Dis $ \_ c (ListContext n ss) ->+            c n (ListContext (n+1) ss)++    freshenStatement s =+        case s of+          SWeight _ _    -> return (s, mempty)+          SBind x body i -> do+               l  <- freshenVar x+               x' <- mkLoc (varHint x) l (map indVar i)+               return (SBind l body i, singletonAssocs x x')+          SLet  x body i -> do+               l  <- freshenVar x+               x' <- mkLoc (varHint x) l (map indVar i)+               return (SLet l body i, singletonAssocs x x')+          SGuard xs pat scrutinee i -> do+               ls  <- freshenVars xs+               xs' <- mkLocs ls (map indVar i)+               return (SGuard ls pat scrutinee i, toAssocs1 xs xs')++    getIndices =  Dis $ \i c -> c i++    unsafePush s =+        Dis $ \_ c (ListContext i ss) ->+            c () (ListContext i (s:ss))++    -- N.B., the use of 'reverse' is necessary so that the order+    -- of pushing matches that of 'pushes'+    unsafePushes ss =+        Dis $ \_ c (ListContext i ss') ->+            c () (ListContext i (reverse ss ++ ss'))++    select l p = loop []+        where+        -- TODO: use a DList to avoid reversing inside 'unsafePushes'+        loop ss = do+            ms <- unsafePop+            case ms of+                Nothing      -> do+                    unsafePushes ss+                    return Nothing+                Just s ->+                    -- Alas, @p@ will have to recheck 'isBoundBy'+                    -- in order to grab the 'Refl' proof we erased;+                    -- but there's nothing to be done for it.+                    case l `isBoundBy` s >> p s of+                    Nothing -> loop (s:ss)+                    Just mr -> do+                        r <- mr+                        unsafePushes ss+                        return (Just r)++withIndices :: [Index (abt '[])] -> Dis abt a -> Dis abt a+withIndices inds (Dis m) = Dis $ \_ c -> m inds c++-- | Not exported because we only need it for defining 'select' on 'Dis'.+unsafePop :: Dis abt (Maybe (Statement abt 'Impure))+unsafePop =+    Dis $ \_ c h@(ListContext i ss) loc ->+        case ss of+        []    -> c Nothing  h loc+        s:ss' -> c (Just s) (ListContext i ss') loc++pushPlate+    :: (ABT Term abt)+    => abt '[] 'HNat+    -> abt '[ 'HNat ] ('HMeasure a)+    -> Dis abt (Variable ('HArray a))+pushPlate n e =+  caseBind e $ \x body -> do+    inds <- getIndices+    i    <- freshInd n+    p    <- freshVar Text.empty (sUnMeasure $ typeOf body)+    unsafePush (SBind p (Thunk $ rename x (indVar i) body)+                (extendIndices i inds))+    mkMultiLoc Text.empty p (map indVar inds)++----------------------------------------------------------------+----------------------------------------------------------------++-- | It is impossible to satisfy the constraints, or at least we+-- give up on trying to do so. This function is identical to 'empty'+-- and 'mzero' for 'Dis'; we just give it its own name since this is+-- the name used in our papers.+--+-- TODO: add some sort of trace information so we can get a better+-- idea what caused a disintegration to fail.+bot :: (ABT Term abt) => Dis abt a+bot = Dis $ \_ _ _ _ -> []+++-- | The empty measure is a solution to the constraints.+-- reject :: (ABT Term abt) => Dis abt a+-- reject = Dis $ \_ _ -> [syn (Superpose_ [])]+++-- Something essentially like this function was called @insert_@+-- in the finally-tagless code.+--+-- | Emit some code that binds a variable, and return the variable+-- thus bound. The function says what to wrap the result of the+-- continuation with; i.e., what we're actually emitting.+emit+    :: (ABT Term abt)+    => Text+    -> Sing a+    -> (forall r. abt '[a] ('HMeasure r) -> abt '[] ('HMeasure r))+    -> Dis abt (Variable a)+emit hint typ f = do+    x <- freshVar hint typ+    Dis $ \_ c h l -> (f . bind x) <$> c x h l+++-- This function was called @lift@ in the finally-tagless code.+-- | Emit an 'MBind' (i.e., \"@m >>= \x ->@\") and return the+-- variable thus bound (i.e., @x@).+emitMBind :: (ABT Term abt) => abt '[] ('HMeasure a) -> Dis abt (Variable a)+emitMBind m =+    emit Text.empty (sUnMeasure $ typeOf m) $ \e ->+        syn (MBind :$ m :* e :* End)+++-- | A smart constructor for emitting let-bindings. If the input+-- is already a variable then we just return it; otherwise we emit+-- the let-binding. N.B., this function provides the invariant that+-- the result is in fact a variable; whereas 'emitLet'' does not.+emitLet :: (ABT Term abt) => abt '[] a -> Dis abt (Variable a)+emitLet e =+    caseVarSyn e return $ \_ ->+        emit Text.empty (typeOf e) $ \m ->+            syn (Let_ :$ e :* m :* End)++-- | A smart constructor for emitting let-bindings. If the input+-- is already a variable or a literal constant, then we just return+-- it; otherwise we emit the let-binding. N.B., this function+-- provides weaker guarantees on the type of the result; if you+-- require the result to always be a variable, then see 'emitLet'+-- instead.+emitLet' :: (ABT Term abt) => abt '[] a -> Dis abt (abt '[] a)+emitLet' e =+    caseVarSyn e (const $ return e) $ \t ->+        case t of+        Literal_ _ -> return e+        _          -> do+            x <- emit Text.empty (typeOf e) $ \m ->+                syn (Let_ :$ e :* m :* End)+            return (var x)++-- | A smart constructor for emitting \"unpair\". If the input+-- argument is actually a constructor then we project out the two+-- components; otherwise we emit the case-binding and return the+-- two variables.+emitUnpair+    :: (ABT Term abt)+    => Whnf abt (HPair a b)+    -> Dis abt (abt '[] a, abt '[] b)+emitUnpair (Head_   w) = return $ reifyPair w+emitUnpair (Neutral e) = do+    let (a,b) = sUnPair (typeOf e)+    x <- freshVar Text.empty a+    y <- freshVar Text.empty b+    emitUnpair_ x y e++emitUnpair_+    :: forall abt a b+    .  (ABT Term abt)+    => Variable a+    -> Variable b+    -> abt '[] (HPair a b)+    -> Dis abt (abt '[] a, abt '[] b)+emitUnpair_ x y = loop+    where+    done :: abt '[] (HPair a b) -> Dis abt (abt '[] a, abt '[] b)+    done e =+#ifdef __TRACE_DISINTEGRATE__+        trace "-- emitUnpair: done (term is not Datum_ nor Case_)" $+#endif+        Dis $ \_ c h l ->+            ( syn+            . Case_ e+            . (:[])+            . Branch (pPair PVar PVar)+            . bind x+            . bind y+            ) <$> c (var x, var y) h l++    loop :: abt '[] (HPair a b) -> Dis abt (abt '[] a, abt '[] b)+    loop e0 =+        caseVarSyn e0 (done . var) $ \t ->+            case t of+            Datum_ d   -> do+#ifdef __TRACE_DISINTEGRATE__+                trace "-- emitUnpair: found Datum_" $ return ()+#endif+                return $ reifyPair (WDatum d)+            Case_ e bs -> do+#ifdef __TRACE_DISINTEGRATE__+                trace "-- emitUnpair: going under Case_" $ return ()+#endif+                -- TODO: we want this to duplicate the current+                -- continuation for (the evaluation of @loop@ in)+                -- all branches. So far our traces all end up+                -- returning @bot@ on the first branch, and hence+                -- @bot@ for the whole case-expression, so we can't+                -- quite tell whether it does what is intended.+                --+                -- N.B., the only 'Dis'-effects in 'applyBranch'+                -- are to freshen variables; thus this use of+                -- 'traverse' is perfectly sound.+                emitCaseWith loop e bs+            _ -> done e0+++-- TODO: emitUneither+++-- This function was called @insert_@ in the old finally-tagless code.+-- | Emit some code that doesn't bind any variables. This function+-- provides an optimisation over using 'emit' and then discarding+-- the generated variable.+emit_+    :: (ABT Term abt)+    => (forall r. abt '[] ('HMeasure r) -> abt '[] ('HMeasure r))+    -> Dis abt ()+emit_ f = Dis $ \_ c h l -> f <$> c () h l+++-- | Emit an 'MBind' that discards its result (i.e., \"@m >>@\").+-- We restrict the type of the argument to be 'HUnit' so as to avoid+-- accidentally dropping things.+emitMBind_ :: (ABT Term abt) => abt '[] ('HMeasure HUnit) -> Dis abt ()+emitMBind_ m = emit_ (m P.>>)+++-- TODO: if the argument is a value, then we can evaluate the 'P.if_' immediately rather than emitting it.+-- | Emit an assertion that the condition is true.+emitGuard :: (ABT Term abt) => abt '[] HBool -> Dis abt ()+emitGuard b = emit_ (P.withGuard b) -- == emit_ $ \m -> P.if_ b m P.reject++-- TODO: if the argument is the literal 1, then we can avoid emitting anything.+emitWeight :: (ABT Term abt) => abt '[] 'HProb -> Dis abt ()+emitWeight w = emit_ (P.withWeight w)+++-- N.B., this use of 'T.traverse' is definitely correct. It's+-- sequentializing @t [abt '[] ('HMeasure a)]@ into @[t (abt '[]+-- ('HMeasure a))]@ by chosing one of the possibilities at each+-- position in @t@. No heap\/context effects can escape to mess+-- things up. In contrast, using 'T.traverse' to sequentialize @t+-- (Dis abt a)@ as @Dis abt (t a)@ is /wrong/! Doing that would give+-- the conjunctive semantics where we have effects from one position+-- in @t@ escape to affect the other positions. This has to do with+-- the general issue in partial evaluation where we need to duplicate+-- downstream work (as we do by passing the same heap to everyone)+-- because there's no general way to combing the resulting heaps+-- for each branch.+--+-- | Run each of the elements of the traversable using the same+-- heap and continuation for each one, then pass the results to a+-- function for emitting code.+emitFork_+    :: (ABT Term abt, T.Traversable t)+    => (forall r. t (abt '[] ('HMeasure r)) -> abt '[] ('HMeasure r))+    -> t (Dis abt a)+    -> Dis abt a+emitFork_ f ms = Dis $ \i c h l -> f <$> T.traverse (\m -> unDis m i c h l) ms+++-- | Emit a 'Superpose_' of the alternatives, each with unit weight.+emitSuperpose+    :: (ABT Term abt)+    => [abt '[] ('HMeasure a)]+    -> Dis abt (Variable a)+emitSuperpose []  = error "TODO: emitSuperpose[]"+emitSuperpose [e] = emitMBind e+emitSuperpose es  =+    emitMBind . P.superpose . NE.map ((,) P.one) $ NE.fromList es+++-- | Emit a 'Superpose_' of the alternatives, each with unit weight.+choose :: (ABT Term abt) => [Dis abt a] -> Dis abt a+choose []  = error "TODO: choose[]"+choose [m] = m+choose ms  = emitFork_ (P.superpose . NE.map ((,) P.one) . NE.fromList) ms+++-- | Given some function we can call on the bodies of the branches,+-- freshen all the pattern-bound variables and then run the function+-- on all the branches in parallel (i.e., with the same continuation+-- and heap) and then emit a case-analysis expression with the+-- results of the continuations as the bodies of the branches. This+-- function is useful for when we really do want to emit a 'Case_'+-- expression, rather than doing the superpose of guard patterns+-- thing that 'constrainValue' does.+--+-- N.B., this function assumes (and does not verify) that the second+-- argument is emissible. So callers must guarantee this invariant,+-- by calling 'atomize' as necessary.+--+-- TODO: capture the emissibility requirement on the second argument+-- in the types.+emitCaseWith+    :: (ABT Term abt)+    => (abt '[] b -> Dis abt r)+    -> abt '[] a+    -> [Branch a abt b]+    -> Dis abt r+emitCaseWith f e bs = do+    gms <- T.for bs $ \(Branch pat body) ->+        let (vars, body') = caseBinds body+        in  (\vars' ->+                let rho = toAssocs1 vars vars'+                in  GBranch pat vars' (f $ renames rho body')+            ) <$> freshenVars vars+    Dis $ \i c h l ->+        (syn . Case_ e) <$> T.for gms (\gm ->+            fromGBranch <$> T.for gm (\m ->+                unDis m i c h l))+{-# INLINE emitCaseWith #-}+++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Evaluation/EvalMonad.hs view
@@ -0,0 +1,339 @@+{-# LANGUAGE CPP+           , GADTs+           , KindSignatures+           , DataKinds+           , Rank2Types+           , ScopedTypeVariables+           , MultiParamTypeClasses+           , FlexibleContexts+           , FlexibleInstances+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.05.24+-- |+-- Module      :  Language.Hakaru.Evaluation.EvalMonad+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+--+----------------------------------------------------------------+module Language.Hakaru.Evaluation.EvalMonad+    ( runPureEvaluate+    , pureEvaluate++    -- * The pure-evaluation monad+    -- ** List-based version+    , ListContext(..), PureAns, Eval(..), runEval+    , residualizePureListContext+    -- ** TODO: IntMap-based version+    ) where++import           Prelude              hiding (id, (.))+import           Control.Category     (Category(..))+#if __GLASGOW_HASKELL__ < 710+import           Data.Functor         ((<$>))+import           Control.Applicative  (Applicative(..))+#endif+import qualified Data.Foldable        as F++import Language.Hakaru.Syntax.IClasses (Some2(..))+import Language.Hakaru.Syntax.Variable (memberVarSet)+import Language.Hakaru.Syntax.ABT      (ABT(..), subst, maxNextFree)+import Language.Hakaru.Syntax.DatumABT+import Language.Hakaru.Syntax.AST+import Language.Hakaru.Evaluation.Types+import Language.Hakaru.Evaluation.Lazy (TermEvaluator, evaluate, defaultCaseEvaluator)+import Language.Hakaru.Evaluation.PEvalMonad (ListContext(..))+++-- The rest of these are just for the emit code, which isn't currently exported.+import           Data.Text             (Text)+import qualified Data.Text             as Text+import qualified Data.Traversable      as T+import Language.Hakaru.Syntax.IClasses (Functor11(..))+import Language.Hakaru.Syntax.Variable (Variable(), toAssocs1)+import Language.Hakaru.Syntax.ABT      (caseVarSyn, caseBinds, substs)+import Language.Hakaru.Types.DataKind+import Language.Hakaru.Types.Sing      (Sing, sUnPair)+import Language.Hakaru.Syntax.TypeOf   (typeOf)+import Language.Hakaru.Syntax.Datum+import Language.Hakaru.Evaluation.Lazy (reifyPair)+#ifdef __TRACE_DISINTEGRATE__+import Debug.Trace                     (trace)+#endif++----------------------------------------------------------------+----------------------------------------------------------------+-- | Call 'evaluate' on a term. This variant returns an @abt@ expression itself so you needn't worry about the 'Eval' monad. For the monadic-version, see 'pureEvaluate'.+--+-- BUG: now that we've indexed 'ListContext' by a 'Purity', does exposing the implementation details still enable clients to break our invariants?+runPureEvaluate :: (ABT Term abt) => abt '[] a -> abt '[] a+runPureEvaluate e = runEval (fromWhnf <$> pureEvaluate e) [Some2 e]+++-- 'evaluate' itself can never @lub@ or @bot@, as captured by the+-- fact that it's type doesn't include 'Alternative' nor 'MonadPlus'+-- constraints. So non-singularity of results could only come from+-- calling @perform@. However, we will never call perform because: (a) the initial heap must be 'Pure' so we will never call @perform@ for a statement on the initial heap, and (b) 'evaluate' itself will never push impure statements so we will never call @perform@ for the statements we push either.+--+-- | Call 'evaluate' on a term. This variant returns something in the 'Eval' monad so you can string multiple evaluation calls together. For the non-monadic version, see 'runPureEvaluate'.+pureEvaluate :: (ABT Term abt) => TermEvaluator abt (Eval abt)+pureEvaluate = evaluate (brokenInvariant "perform") defaultCaseEvaluator+++----------------------------------------------------------------+type PureAns abt a = ListContext abt 'Pure -> abt '[] a++newtype Eval abt x =+    Eval { unEval :: forall a. (x -> PureAns abt a) -> PureAns abt a }++brokenInvariant :: String -> a+brokenInvariant loc = error (loc ++ ": Eval's invariant broken")+++-- | Run a computation in the 'Eval' monad, residualizing out all the+-- statements in the final evaluation context. The second argument+-- should include all the terms altered by the 'Eval' expression; this+-- is necessary to ensure proper hygiene; for example(s):+--+-- > runEval (pureEvaluate e) [Some2 e]+--+-- We use 'Some2' on the inputs because it doesn't matter what their+-- type or locally-bound variables are, so we want to allow @f@ to+-- contain terms with different indices.+runEval :: (ABT Term abt, F.Foldable f)+    => Eval abt (abt '[] a)+    -> f (Some2 abt)+    -> abt '[] a+runEval (Eval m) es =+    m residualizePureListContext (ListContext (maxNextFree es) [])+    ++residualizePureListContext+    :: forall abt a+    .  (ABT Term abt)+    => abt '[] a+    -> ListContext abt 'Pure+    -> abt '[] a+residualizePureListContext e0 =+    foldl step e0 . statements+    where+    -- TODO: make paremetric in the purity, so we can combine 'residualizeListContext' with this function.+    step :: abt '[] a -> Statement abt 'Pure -> abt '[] a+    step e s =+        case s of+        SLet x body _+            | not (x `memberVarSet` freeVars e) -> e+            -- TODO: if used exactly once in @e@, then inline.+            | otherwise ->+                case getLazyVariable body of+                Just y  -> subst x (var y) e+                Nothing ->+                    case getLazyLiteral body of+                    Just v  -> subst x (syn $ Literal_ v) e+                    Nothing ->+                        syn (Let_ :$ fromLazy body :* bind x e :* End)+                ++----------------------------------------------------------------+instance Functor (Eval abt) where+    fmap f (Eval m) = Eval $ \c -> m (c . f)++instance Applicative (Eval abt) where+    pure x              = Eval $ \c -> c x+    Eval mf <*> Eval mx = Eval $ \c -> mf $ \f -> mx $ \x -> c (f x)++instance Monad (Eval abt) where+    return       = pure+    Eval m >>= k = Eval $ \c -> m $ \x -> unEval (k x) c++instance (ABT Term abt) => EvaluationMonad abt (Eval abt) 'Pure where+    freshNat =+        Eval $ \c (ListContext i ss) ->+            c i (ListContext (i+1) ss)++    unsafePush s =+        Eval $ \c (ListContext i ss) ->+            c () (ListContext i (s:ss))++    -- N.B., the use of 'reverse' is necessary so that the order+    -- of pushing matches that of 'pushes'+    unsafePushes ss =+        Eval $ \c (ListContext i ss') ->+            c () (ListContext i (reverse ss ++ ss'))++    select x p = loop []+        where+        -- TODO: use a DList to avoid reversing inside 'unsafePushes'+        loop ss = do+            ms <- unsafePop+            case ms of+                Nothing -> do+                    unsafePushes ss+                    return Nothing+                Just s  ->+                    -- Alas, @p@ will have to recheck 'isBoundBy'+                    -- in order to grab the 'Refl' proof we erased;+                    -- but there's nothing to be done for it.+                    case x `isBoundBy` s >> p s of+                    Nothing -> loop (s:ss)+                    Just mr -> do+                        r <- mr+                        unsafePushes ss+                        return (Just r)++-- TODO: make paremetric in the purity+-- | Not exported because we only need it for defining 'select' on 'Eval'.+unsafePop :: Eval abt (Maybe (Statement abt 'Pure))+unsafePop =+    Eval $ \c h@(ListContext i ss) ->+        case ss of+        []    -> c Nothing  h+        s:ss' -> c (Just s) (ListContext i ss')+++----------------------------------------------------------------+----------------------------------------------------------------+-- | Emit some code that binds a variable, and return the variable+-- thus bound. The function says what to wrap the result of the+-- continuation with; i.e., what we're actually emitting.+emit+    :: (ABT Term abt)+    => Text+    -> Sing a+    -> (forall r. abt '[a] r -> abt '[] r)+    -> Eval abt (Variable a)+emit hint typ f = do+    x <- freshVar hint typ+    Eval $ \c h -> (f . bind x) $ c x h+++-- | A smart constructor for emitting let-bindings. If the input+-- is already a variable then we just return it; otherwise we emit+-- the let-binding. N.B., this function provides the invariant that+-- the result is in fact a variable; whereas 'emitLet'' does not.+emitLet :: (ABT Term abt) => abt '[] a -> Eval abt (Variable a)+emitLet e =+    caseVarSyn e return $ \_ ->+        emit Text.empty (typeOf e) $ \f ->+            syn (Let_ :$ e :* f :* End)++-- | A smart constructor for emitting let-bindings. If the input+-- is already a variable or a literal constant, then we just return+-- it; otherwise we emit the let-binding. N.B., this function+-- provides weaker guarantees on the type of the result; if you+-- require the result to always be a variable, then see 'emitLet'+-- instead.+emitLet' :: (ABT Term abt) => abt '[] a -> Eval abt (abt '[] a)+emitLet' e =+    caseVarSyn e (const $ return e) $ \t ->+        case t of+        Literal_ _ -> return e+        _          -> do+            x <- emit Text.empty (typeOf e) $ \f ->+                syn (Let_ :$ e :* f :* End)+            return (var x)++-- | A smart constructor for emitting \"unpair\". If the input+-- argument is actually a constructor then we project out the two+-- components; otherwise we emit the case-binding and return the+-- two variables.+emitUnpair+    :: (ABT Term abt)+    => Whnf abt (HPair a b)+    -> Eval abt (abt '[] a, abt '[] b)+emitUnpair (Head_   w) = return $ reifyPair w+emitUnpair (Neutral e) = do+    let (a,b) = sUnPair (typeOf e)+    x <- freshVar Text.empty a+    y <- freshVar Text.empty b+    emitUnpair_ x y e++emitUnpair_+    :: forall abt a b+    .  (ABT Term abt)+    => Variable a+    -> Variable b+    -> abt '[] (HPair a b)+    -> Eval abt (abt '[] a, abt '[] b)+emitUnpair_ x y = loop+    where+    done :: abt '[] (HPair a b) -> Eval abt (abt '[] a, abt '[] b)+    done e =+#ifdef __TRACE_DISINTEGRATE__+        trace "-- emitUnpair: done (term is not Datum_ nor Case_)" $+#endif+        Eval $ \c h ->+            ( syn+            . Case_ e+            . (:[])+            . Branch (pPair PVar PVar)+            . bind x+            . bind y+            ) $ c (var x, var y) h++    loop :: abt '[] (HPair a b) -> Eval abt (abt '[] a, abt '[] b)+    loop e0 =+        caseVarSyn e0 (done . var) $ \t ->+            case t of+            Datum_ d   -> do+#ifdef __TRACE_DISINTEGRATE__+                trace "-- emitUnpair: found Datum_" $ return ()+#endif+                return $ reifyPair (WDatum d)+            Case_ e bs -> do+#ifdef __TRACE_DISINTEGRATE__+                trace "-- emitUnpair: going under Case_" $ return ()+#endif+                -- TODO: we want this to duplicate the current+                -- continuation for (the evaluation of @loop@ in)+                -- all branches. So far our traces all end up+                -- returning @bot@ on the first branch, and hence+                -- @bot@ for the whole case-expression, so we can't+                -- quite tell whether it does what is intended.+                --+                -- N.B., the only 'Eval'-effects in 'applyBranch'+                -- are to freshen variables; thus this use of+                -- 'traverse' is perfectly sound.+                emitCaseWith loop e bs+            _ -> done e0++-- TODO: emitUneither++-- | Run each of the elements of the traversable using the same+-- heap and continuation for each one, then pass the results to a+-- function for emitting code.+emitFork_+    :: (ABT Term abt, T.Traversable t)+    => (forall r. t (abt '[] r) -> abt '[] r)+    -> t (Eval abt a)+    -> Eval abt a+emitFork_ f ms =+    Eval $ \c h -> f $ fmap (\m -> unEval m c h) ms+++emitCaseWith+    :: (ABT Term abt)+    => (abt '[] b -> Eval abt r)+    -> abt '[] a+    -> [Branch a abt b]+    -> Eval abt r+emitCaseWith f e bs = do+    gms <- T.for bs $ \(Branch pat body) ->+        let (vars, body') = caseBinds body+        in  (\vars' ->+                let rho = toAssocs1 vars (fmap11 var vars')+                in  GBranch pat vars' (f $ substs rho body')+            ) <$> freshenVars vars+    Eval $ \c h ->+        syn (Case_ e+            (map (fromGBranch . fmap (\m -> unEval m c h)) gms))+{-# INLINE emitCaseWith #-}++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Evaluation/ExpectMonad.hs view
@@ -0,0 +1,213 @@+{-# LANGUAGE CPP+           , GADTs+           , KindSignatures+           , DataKinds+           , Rank2Types+           , ScopedTypeVariables+           , MultiParamTypeClasses+           , FlexibleContexts+           , FlexibleInstances+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.04.24+-- |+-- Module      :  Language.Hakaru.Evaluation.ExpectMonad+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+--+----------------------------------------------------------------+module Language.Hakaru.Evaluation.ExpectMonad+    ( pureEvaluate+    +    -- * The expectation-evaluation monad+    -- ** List-based version+    , ListContext(..), ExpectAns, Expect(..), runExpect+    , residualizeExpectListContext+    -- ** TODO: IntMap-based version+    +    -- * ...+    , emit+    , emit_+    ) where++import           Prelude              hiding (id, (.))+import           Control.Category     (Category(..))+#if __GLASGOW_HASKELL__ < 710+import           Data.Functor         ((<$>))+import           Control.Applicative  (Applicative(..))+#endif+import qualified Data.Foldable        as F++import Language.Hakaru.Syntax.IClasses (Some2(..))+import Language.Hakaru.Syntax.ABT      (ABT(..), caseVarSyn, subst, maxNextFreeOrBind)+import Language.Hakaru.Syntax.Variable (memberVarSet)+import Language.Hakaru.Syntax.AST      hiding (Expect)+import Language.Hakaru.Evaluation.Types+import Language.Hakaru.Evaluation.Lazy (TermEvaluator, evaluate, defaultCaseEvaluator)+import Language.Hakaru.Evaluation.PEvalMonad (ListContext(..))+++-- The rest of these are just for the emit code, which isn't currently exported.+import Data.Text                       (Text)+import Language.Hakaru.Syntax.Variable (Variable())+import Language.Hakaru.Types.DataKind+import Language.Hakaru.Types.Sing      (Sing)+#ifdef __TRACE_DISINTEGRATE__+import Debug.Trace                     (trace)+#endif++----------------------------------------------------------------+----------------------------------------------------------------+type ExpectAns abt = ListContext abt 'ExpectP -> abt '[] 'HProb++newtype Expect abt x =+    Expect { unExpect :: (x -> ExpectAns abt) -> ExpectAns abt }++residualizeExpectListContext+    :: forall abt+    .  (ABT Term abt)+    => abt '[] 'HProb+    -> ListContext abt 'ExpectP+    -> abt '[] 'HProb+residualizeExpectListContext e0 =+    foldl step e0 . statements+    where+    -- TODO: make paremetric in the purity, so we can combine 'residualizeListContext' with this function.+    step :: abt '[] 'HProb -> Statement abt 'ExpectP -> abt '[] 'HProb+    step e s =+        case s of+        SLet x body _+            -- BUG: this trick for dropping unused let-bindings doesn't seem to work anymore... (cf., 'Tests.Expect.test4')+            | not (x `memberVarSet` freeVars e) -> e+            -- TODO: if used exactly once in @e@, then inline.+            | otherwise ->+                case getLazyVariable body of+                Just y  -> subst x (var y) e+                Nothing ->+                    case getLazyLiteral body of+                    Just v  -> subst x (syn $ Literal_ v) e+                    Nothing ->+                        syn (Let_ :$ fromLazy body :* bind x e :* End)+        SStuff0    f _ -> f e+        SStuff1 _x f _ -> f e+++pureEvaluate :: (ABT Term abt) => TermEvaluator abt (Expect abt)+pureEvaluate = evaluate (brokenInvariant "perform") defaultCaseEvaluator++brokenInvariant :: String -> a+brokenInvariant loc = error (loc ++ ": Expect's invariant broken")+++-- | Run a computation in the 'Expect' monad, residualizing out all+-- the statements in the final evaluation context. The second+-- argument should include all the terms altered by the 'Eval'+-- expression; this is necessary to ensure proper hygiene; for+-- example(s):+--+-- > runExpect (pureEvaluate e) [Some2 e]+--+-- We use 'Some2' on the inputs because it doesn't matter what their+-- type or locally-bound variables are, so we want to allow @f@ to+-- contain terms with different indices.+runExpect+    :: forall abt f a+    .  (ABT Term abt, F.Foldable f)+    => Expect abt (abt '[] a)+    -> abt '[a] 'HProb+    -> f (Some2 abt)+    -> abt '[] 'HProb+runExpect (Expect m) f es =+    m c0 h0+    where+    i0   = nextFreeOrBind f `max` maxNextFreeOrBind es+    h0   = ListContext i0 []+    c0 e =+        residualizeExpectListContext $+        caseVarSyn e+            (\x -> caseBind f $ \y f' -> subst y (var x) f')+            (\_ -> syn (Let_ :$ e :* f :* End))+        -- TODO: make this smarter still, to drop the let-binding entirely if it's not used in @f@.+++----------------------------------------------------------------+instance Functor (Expect abt) where+    fmap f (Expect m) = Expect $ \c -> m (c . f)++instance Applicative (Expect abt) where+    pure x                  = Expect $ \c -> c x+    Expect mf <*> Expect mx = Expect $ \c -> mf $ \f -> mx $ \x -> c (f x)++instance Monad (Expect abt) where+    return         = pure+    Expect m >>= k = Expect $ \c -> m $ \x -> unExpect (k x) c++instance (ABT Term abt) => EvaluationMonad abt (Expect abt) 'ExpectP where+    freshNat =+        Expect $ \c (ListContext i ss) ->+            c i (ListContext (i+1) ss)++    unsafePush s =+        Expect $ \c (ListContext i ss) ->+            c () (ListContext i (s:ss))++    -- N.B., the use of 'reverse' is necessary so that the order+    -- of pushing matches that of 'pushes'+    unsafePushes ss =+        Expect $ \c (ListContext i ss') ->+            c () (ListContext i (reverse ss ++ ss'))++    select x p = loop []+        where+        -- TODO: use a DList to avoid reversing inside 'unsafePushes'+        loop ss = do+            ms <- unsafePop+            case ms of+                Nothing -> do+                    unsafePushes ss+                    return Nothing+                Just s  ->+                    -- Alas, @p@ will have to recheck 'isBoundBy'+                    -- in order to grab the 'Refl' proof we erased;+                    -- but there's nothing to be done for it.+                    case x `isBoundBy` s >> p s of+                    Nothing -> loop (s:ss)+                    Just mr -> do+                        r <- mr+                        unsafePushes ss+                        return (Just r)++-- TODO: make paremetric in the purity+-- | Not exported because we only need it for defining 'select' on 'Expect'.+unsafePop :: Expect abt (Maybe (Statement abt 'ExpectP))+unsafePop =+    Expect $ \c h@(ListContext i ss) ->+        case ss of+        []    -> c Nothing  h+        s:ss' -> c (Just s) (ListContext i ss')++----------------------------------------------------------------+emit+    :: (ABT Term abt)+    => Text+    -> Sing a+    -> (abt '[a] 'HProb -> abt '[] 'HProb)+    -> Expect abt (Variable a)+emit hint typ f = do+    x <- freshVar hint typ+    Expect $ \c h -> (f . bind x) $ c x h++emit_+    :: (ABT Term abt)+    => (abt '[] 'HProb -> abt '[] 'HProb)+    -> Expect abt ()+emit_ f = Expect $ \c h -> f $ c () h++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Evaluation/Lazy.hs view
@@ -0,0 +1,814 @@+{-# LANGUAGE CPP+           , GADTs+           , DataKinds+           , KindSignatures+           , MultiParamTypeClasses+           , FunctionalDependencies+           , ScopedTypeVariables+           , FlexibleContexts+           , Rank2Types+           , TypeSynonymInstances+           , FlexibleInstances+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.04.28+-- |+-- Module      :  Language.Hakaru.Evaluation.Lazy+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- Lazy partial evaluation.+--+-- BUG: completely gave up on structure sharing. Need to add that+-- back in. cf., @gvidal-lopstr07lncs.pdf@ for an approach much+-- like my old one.+----------------------------------------------------------------+module Language.Hakaru.Evaluation.Lazy+    (+    -- * Lazy partial evaluation+      TermEvaluator+    , MeasureEvaluator+    , CaseEvaluator+    , VariableEvaluator+    , evaluate+    -- ** Helper functions+    , update+    , defaultCaseEvaluator+    , toStatements++    -- ** Helpers that should really go away+    , Interp(..), reifyPair+    ) where++import           Prelude                hiding (id, (.))+import           Control.Category       (Category(..))+#if __GLASGOW_HASKELL__ < 710+import           Data.Functor           ((<$>))+#endif+import           Control.Monad          ((<=<))+import           Control.Monad.Identity (Identity, runIdentity)+import           Data.Sequence          (Seq)+import qualified Data.Sequence          as Seq+import qualified Data.Text              as Text++import Language.Hakaru.Syntax.IClasses+import Data.Number.Nat+import Data.Number.Natural+import Language.Hakaru.Types.DataKind+import Language.Hakaru.Types.Sing+import Language.Hakaru.Types.Coercion+import Language.Hakaru.Types.HClasses+import Language.Hakaru.Syntax.TypeOf+import Language.Hakaru.Syntax.AST+import Language.Hakaru.Syntax.Datum+import Language.Hakaru.Syntax.DatumCase (DatumEvaluator, MatchResult(..), matchBranches, MatchState(..), matchTopPattern)+import Language.Hakaru.Syntax.ABT+import Language.Hakaru.Evaluation.Types+import qualified Language.Hakaru.Syntax.Prelude as P+{-+-- BUG: can't import this because of cyclic dependency+import qualified Language.Hakaru.Expect         as E+-}++#ifdef __TRACE_DISINTEGRATE__+import Language.Hakaru.Pretty.Haskell (pretty)+import Debug.Trace (trace)+#endif++----------------------------------------------------------------+----------------------------------------------------------------+-- TODO: (eventually) accept an argument dictating the evaluation+-- strategy (HNF, WHNF, full-beta NF,...). The strategy value should+-- probably be a family of singletons, where the type-level strategy+-- @s@ is also an index on the 'Context' and (the renamed) 'Whnf'.+-- That way we don't need to define a bunch of variant 'Context',+-- 'Statement', and 'Whnf' data types; but rather can use indexing+-- to select out subtypes of the generic versions.+++-- | A function for evaluating any term to weak-head normal form.+type TermEvaluator abt m =+    forall a. abt '[] a -> m (Whnf abt a)++-- | A function for \"performing\" an 'HMeasure' monadic action.+-- This could mean actual random sampling, or simulated sampling+-- by generating a new term and returning the newly bound variable,+-- or anything else.+type MeasureEvaluator abt m =+    forall a. abt '[] ('HMeasure a) -> m (Whnf abt a)++-- | A function for evaluating any case-expression to weak-head+-- normal form.+type CaseEvaluator abt m =+    forall a b. abt '[] a -> [Branch a abt b] -> m (Whnf abt b)++-- | A function for evaluating any variable to weak-head normal form.+type VariableEvaluator abt m =+    forall a. Variable a -> m (Whnf abt a)+++-- | Lazy partial evaluation with some given \"perform\" and+-- \"evaluateCase\" functions. The first argument to @evaluateCase@+-- will be the 'TermEvaluator' we're constructing (thus tying the+-- knot). N.B., if @p ~ 'Pure@ then the \"perform\" function will+-- never be called.+--+-- We factor out the 'CaseEvaluator' because some code (e.g.,+-- disintegration) may need to do something special rather than+-- just relying on the 'defaultCaseEvaluator' implementation.+evaluate+    :: forall abt m p+    .  (ABT Term abt, EvaluationMonad abt m p)+    => MeasureEvaluator abt m+    -> (TermEvaluator abt m -> CaseEvaluator abt m)+    -> TermEvaluator    abt m+{-# INLINE evaluate #-}+evaluate perform evaluateCase = evaluate_+    where+    evaluateCase_ :: CaseEvaluator abt m+    evaluateCase_ = evaluateCase evaluate_++    evaluate_ :: TermEvaluator abt m+    evaluate_ e0 =+#ifdef __TRACE_DISINTEGRATE__+      trace ("-- evaluate_: " ++ show (pretty e0)) $+#endif+      caseVarSyn e0 (update perform evaluate_) $ \t ->+        case t of+        -- Things which are already WHNFs+        Literal_ v               -> return . Head_ $ WLiteral v+        Datum_   d               -> return . Head_ $ WDatum   d+        Empty_   typ             -> return . Head_ $ WEmpty   typ+        Array_   e1 e2           -> return . Head_ $ WArray e1 e2+        Lam_  :$ e1 :* End       -> return . Head_ $ WLam   e1+        Dirac :$ e1 :* End       -> return . Head_ $ WDirac e1+        MBind :$ e1 :* e2 :* End -> return . Head_ $ WMBind e1 e2+        Plate :$ e1 :* e2 :* End -> return . Head_ $ WPlate e1 e2+        MeasureOp_ o :$ es       -> return . Head_ $ WMeasureOp o es+        Superpose_ pes           -> return . Head_ $ WSuperpose pes+        Reject_ typ              -> return . Head_ $ WReject typ+        -- We don't bother evaluating these, even though we could...+        Integrate :$ e1 :* e2 :* e3 :* End ->+            return . Head_ $ WIntegrate e1 e2 e3+        Summate h1 h2 :$ e1 :* e2 :* e3 :* End ->+            return . Neutral $ syn t+            --return . Head_ $ WSummate   e1 e2 e3+++        -- Everything else needs some evaluation++        App_ :$ e1 :* e2 :* End -> do+            w1 <- evaluate_ e1+            case w1 of+                Neutral e1' -> return . Neutral $ P.app e1' e2+                Head_   v1  -> evaluateApp v1+            where+            evaluateApp (WLam f)   =+                -- call-by-name:+                caseBind f $ \x f' -> do+                    i <- getIndices+                    push (SLet x (Thunk e2) i) f' evaluate_+            evaluateApp _ = error "evaluate{App_}: the impossible happened"++        Let_ :$ e1 :* e2 :* End -> do+            i <- getIndices+            caseBind e2 $ \x e2' ->+                push (SLet x (Thunk e1) i) e2' evaluate_++        CoerceTo_   c :$ e1 :* End -> coerceTo   c <$> evaluate_ e1+        UnsafeFrom_ c :$ e1 :* End -> coerceFrom c <$> evaluate_ e1++        -- TODO: will maybe clean up the code to map 'evaluate' over @es@ before calling the evaluateFooOp helpers?+        NaryOp_  o    es -> evaluateNaryOp  evaluate_ o es+        ArrayOp_ o :$ es -> evaluateArrayOp evaluate_ o es+        PrimOp_  o :$ es -> evaluatePrimOp  evaluate_ o es++        -- BUG: avoid the chance of looping in case 'E.expect' residualizes!+        -- TODO: use 'evaluate' in 'E.expect' for the evaluation of @e1@+        Expect :$ e1 :* e2 :* End ->+            error "TODO: evaluate{Expect}: unclear how to handle this without cyclic dependencies"+        {-+        -- BUG: can't call E.expect because of cyclic dependency+            evaluate_ . E.expect e1 $ \e3 ->+                syn (Let_ :$ e3 :* e2 :* End)+        -}++        Case_ e bs -> evaluateCase_ e bs++        _ :$ _ -> error "evaluate: the impossible happened"+++-- | A simple 'CaseEvaluator' which uses the 'DatumEvaluator' to+-- force the scrutinee, and if 'matchBranches' succeeds then we+-- call the 'TermEvaluator' to continue evaluating the body of the+-- matched branch. If we 'GotStuck' then we return a 'Neutral' term+-- of the case expression itself (n.b, any side effects from having+-- called the 'DatumEvaluator' will still persist when returning+-- this neutral term). If we didn't get stuck and yet none of the+-- branches matches, then we throw an exception.+defaultCaseEvaluator+    :: forall abt m p+    .  (ABT Term abt, EvaluationMonad abt m p)+    => TermEvaluator abt m+    -> CaseEvaluator abt m+{-# INLINE defaultCaseEvaluator #-}+defaultCaseEvaluator evaluate_ = evaluateCase_+    where+    -- TODO: At present, whenever we residualize a case expression we'll+    -- generate a 'Neutral' term which will, when run, repeat the work+    -- we're doing in the evaluation here. We could eliminate this+    -- redundancy by introducing a new variable for @e@ each time this+    -- function is called--- if only we had some way of getting those+    -- variables put into the right place for when we residualize the+    -- original scrutinee...+    --+    -- N.B., 'DatumEvaluator' is a rank-2 type so it requires a signature+    evaluateDatum :: DatumEvaluator (abt '[]) m+    evaluateDatum e = viewWhnfDatum <$> evaluate_ e++    evaluateCase_ :: CaseEvaluator abt m+    evaluateCase_ e bs = do+        match <- matchBranches evaluateDatum e bs+        case match of+            Nothing ->+                -- TODO: print more info about where this error+                -- happened+                --+                -- TODO: rather than throwing a Haskell error,+                -- instead capture the possibility of failure in+                -- the 'EvaluationMonad' monad.+                error "defaultCaseEvaluator: non-exhaustive patterns in case!"+            Just GotStuck ->+                return . Neutral . syn $ Case_ e bs+            Just (Matched ss body) ->+                pushes (toStatements ss) body evaluate_+++toStatements :: Assocs (abt '[]) -> [Statement abt p]+toStatements = map (\(Assoc x e) -> SLet x (Thunk e) []) . fromAssocs+++----------------------------------------------------------------+-- TODO: figure out how to abstract this so it can be reused by+-- 'constrainValue'. Especially the 'SBranch case of 'step'+--+-- TODO: we could speed up the case for free variables by having+-- the 'Context' also keep track of the largest free var. That way,+-- we can just check up front whether @varID x < nextFreeVarID@.+-- Of course, we'd have to make sure we've sufficiently renamed all+-- bound variables to be above @nextFreeVarID@; but then we have to+-- do that anyways.+update+    :: forall abt m p+    .  (ABT Term abt, EvaluationMonad abt m p)+    => MeasureEvaluator  abt m+    -> TermEvaluator     abt m+    -> VariableEvaluator abt m+update perform evaluate_ = \x ->+    -- If we get 'Nothing', then it turns out @x@ is a free variable+    fmap (maybe (Neutral $ var x) id) . select x $ \s ->+        case s of+        SBind y e i -> do+            Refl <- varEq x y+            Just $ do+                w <- perform $ caseLazy e fromWhnf id+                unsafePush (SLet x (Whnf_ w) i)+#ifdef __TRACE_DISINTEGRATE__+                trace ("-- updated "+                    ++ show (ppStatement 11 s)+                    ++ " to "+                    ++ show (ppStatement 11 (SLet x (Whnf_ w) i))+                    ) $ return ()+#endif+                return w+        SLet y e i -> do+            Refl <- varEq x y+            Just $ do+                w <- caseLazy e return evaluate_+                unsafePush (SLet x (Whnf_ w) i)+                return w+        -- These two don't bind any variables, so they definitely can't match.+        SWeight   _ _ -> Nothing+        SStuff0   _ _ -> Nothing+        -- These two do bind variables, but there's no expression we can return for them because the variables are untouchable\/abstract.+        SStuff1 _ _ _ -> Just . return . Neutral $ var x+        SGuard ys pat scrutinee i -> Just . return . Neutral $ var x+++----------------------------------------------------------------+-- BUG: need to improve the types so they can capture polymorphic data types+-- BUG: this is a **really gross** hack. If we can avoid it, we should!!!+class Interp a a' | a -> a' where+    reify   :: (ABT Term abt) => Head abt a -> a'+    reflect :: (ABT Term abt) => a' -> Head abt a++instance Interp 'HNat Natural where+    reflect = WLiteral . LNat+    reify (WLiteral (LNat n)) = n+    reify (WCoerceTo   _ _) = error "TODO: reify{WCoerceTo}"+    reify (WUnsafeFrom _ _) = error "TODO: reify{WUnsafeFrom}"++instance Interp 'HInt Integer where+    reflect = WLiteral . LInt+    reify (WLiteral (LInt i)) = i+    reify (WCoerceTo   _ _) = error "TODO: reify{WCoerceTo}"+    reify (WUnsafeFrom _ _) = error "TODO: reify{WUnsafeFrom}"++instance Interp 'HProb NonNegativeRational where+    reflect = WLiteral . LProb+    reify (WLiteral (LProb p)) = p+    reify (WCoerceTo   _ _)   = error "TODO: reify{WCoerceTo}"+    reify (WUnsafeFrom _ _)   = error "TODO: reify{WUnsafeFrom}"+    reify (WIntegrate  _ _ _) = error "TODO: reify{WIntegrate}"+    --reify (WSummate    _ _ _) = error "TODO: reify{WSummate}"++instance Interp 'HReal Rational where+    reflect = WLiteral . LReal+    reify (WLiteral (LReal r)) = r+    reify (WCoerceTo   _ _) = error "TODO: reify{WCoerceTo}"+    reify (WUnsafeFrom _ _) = error "TODO: reify{WUnsafeFrom}"+++identifyDatum :: (ABT Term abt) => DatumEvaluator (abt '[]) Identity+identifyDatum = return . (viewWhnfDatum <=< toWhnf)++-- HACK: this requires -XTypeSynonymInstances and -XFlexibleInstances+-- This instance does seem to work; albeit it's trivial...+instance Interp HUnit () where+    reflect () = WDatum dUnit+    reify v = runIdentity $ do+        match <- matchTopPattern identifyDatum (fromHead v) pUnit Nil1+        case match of+            Just (Matched_ _ss Nil1) -> return ()+            _ -> error "reify{HUnit}: the impossible happened"++-- HACK: this requires -XTypeSynonymInstances and -XFlexibleInstances+-- This instance also seems to work...+instance Interp HBool Bool where+    reflect = WDatum . (\b -> if b then dTrue else dFalse)+    reify v = runIdentity $ do+        matchT <- matchTopPattern identifyDatum (fromHead v) pTrue Nil1+        case matchT of+            Just (Matched_ _ss Nil1) -> return True+            Just GotStuck_ -> error "reify{HBool}: the impossible happened"+            Nothing -> do+                matchF <- matchTopPattern identifyDatum (fromHead v) pFalse Nil1+                case matchF of+                    Just (Matched_ _ss Nil1) -> return False+                    _ -> error "reify{HBool}: the impossible happened"+++-- TODO: can't we just use 'viewHeadDatum' and match on that?+reifyPair+    :: (ABT Term abt) => Head abt (HPair a b) -> (abt '[] a, abt '[] b)+reifyPair v =+    let impossible = error "reifyPair: the impossible happened"+        e0    = fromHead v+        n     = nextFree e0+        (a,b) = sUnPair $ typeOf e0+        x = Variable Text.empty n       a+        y = Variable Text.empty (1 + n) b++    in runIdentity $ do+        match <- matchTopPattern identifyDatum e0 (pPair PVar PVar) (Cons1 x (Cons1 y Nil1))+        case match of+            Just (Matched_ ss Nil1) ->+                case ss [] of+                [Assoc x' e1, Assoc y' e2] ->+                    maybe impossible id $ do+                        Refl <- varEq x x'+                        Refl <- varEq y y'+                        Just $ return (e1, e2)+                _ -> impossible+            _ -> impossible+{-+instance Interp (HPair a b) (abt '[] a, abt '[] b) where+    reflect (a,b) = P.pair a b+    reify = reifyPair++instance Interp (HEither a b) (Either (abt '[] a) (abt '[] b)) where+    reflect (Left  a) = P.left  a+    reflect (Right b) = P.right b+    reify =++instance Interp (HMaybe a) (Maybe (abt '[] a)) where+    reflect Nothing  = P.nothing+    reflect (Just a) = P.just a+    reify =++data ListHead (a :: Hakaru)+    = NilHead+    | ConsHead (abt '[] a) (abt '[] (HList a)) -- modulo scoping of @abt@++instance Interp (HList a) (ListHead a) where+    reflect []     = P.nil+    reflect (x:xs) = P.cons x xs+    reify =+-}+++impl, diff, nand, nor :: Bool -> Bool -> Bool+impl x y = not x || y+diff x y = x && not y+nand x y = not (x && y)+nor  x y = not (x || y)++-- BUG: no Floating instance for LogFloat (nor NonNegativeRational), so can't actually use this...+natRoot :: (Floating a) => a -> Nat -> a+natRoot x y = x ** recip (fromIntegral (fromNat y))+++----------------------------------------------------------------+evaluateNaryOp+    :: (ABT Term abt, EvaluationMonad abt m p)+    => TermEvaluator abt m+    -> NaryOp a+    -> Seq (abt '[] a)+    -> m (Whnf abt a)+evaluateNaryOp evaluate_ = \o es -> mainLoop o (evalOp o) Seq.empty es+    where+    -- TODO: there's got to be a more efficient way to do this...+    mainLoop o op ws es =+        case Seq.viewl es of+        Seq.EmptyL   -> return $+            case Seq.viewl ws of+            Seq.EmptyL         -> identityElement o -- Avoid empty naryOps+            w Seq.:< ws'+                | Seq.null ws' -> w -- Avoid singleton naryOps+                | otherwise    ->+                    Neutral . syn . NaryOp_ o $ fmap fromWhnf ws+        e Seq.:< es' -> do+            w <- evaluate_ e+            case matchNaryOp o w of+                Nothing  -> mainLoop o op (snocLoop op ws w) es'+                Just es2 -> mainLoop o op ws (es2 Seq.>< es')++    snocLoop+        :: (ABT syn abt)+        => (Head abt a -> Head abt a -> Head abt a)+        -> Seq (Whnf abt a)+        -> Whnf abt a+        -> Seq (Whnf abt a)+    snocLoop op ws w1 =+        -- TODO: immediately return @ws@ if @w1 == identityElement o@ (whenever identityElement is defined)+        case Seq.viewr ws of+        Seq.EmptyR    -> Seq.singleton w1+        ws' Seq.:> w2 ->+            case (w1,w2) of+            (Head_ v1, Head_ v2) -> snocLoop op ws' (Head_ (op v1 v2))+            _                    -> ws Seq.|> w1++    matchNaryOp+        :: (ABT Term abt)+        => NaryOp a+        -> Whnf abt a+        -> Maybe (Seq (abt '[] a))+    matchNaryOp o w =+        case w of+        Head_   _ -> Nothing+        Neutral e ->+            caseVarSyn e (const Nothing) $ \t ->+                case t of+                NaryOp_ o' es | o' == o -> Just es+                _                       -> Nothing++    -- TODO: move this off to Prelude.hs or somewhere...+    identityElement :: (ABT Term abt) => NaryOp a -> Whnf abt a+    identityElement o =+        case o of+        And    -> Head_ (WDatum dTrue)+        Or     -> Head_ (WDatum dFalse)+        Xor    -> Head_ (WDatum dFalse)+        Iff    -> Head_ (WDatum dTrue)+        Min  _ -> Neutral (syn (NaryOp_ o Seq.empty)) -- no identity in general (but we could do it by cases...)+        Max  _ -> Neutral (syn (NaryOp_ o Seq.empty)) -- no identity in general (but we could do it by cases...)+        -- TODO: figure out how to reuse 'P.zero_' and 'P.one_' here; requires converting thr @(syn . Literal_)@ into @(Head_ . WLiteral)@. Maybe we should change 'P.zero_' and 'P.one_' so they just return the 'Literal' itself rather than the @abt@?+        Sum  HSemiring_Nat  -> Head_ (WLiteral (LNat  0))+        Sum  HSemiring_Int  -> Head_ (WLiteral (LInt  0))+        Sum  HSemiring_Prob -> Head_ (WLiteral (LProb 0))+        Sum  HSemiring_Real -> Head_ (WLiteral (LReal 0))+        Prod HSemiring_Nat  -> Head_ (WLiteral (LNat  1))+        Prod HSemiring_Int  -> Head_ (WLiteral (LInt  1))+        Prod HSemiring_Prob -> Head_ (WLiteral (LProb 1))+        Prod HSemiring_Real -> Head_ (WLiteral (LReal 1))++    -- | The evaluation interpretation of each NaryOp+    evalOp+        :: (ABT Term abt)+        => NaryOp a+        -> Head abt a+        -> Head abt a+        -> Head abt a+    -- TODO: something more efficient\/direct if we can...+    evalOp And      = \v1 v2 -> reflect (reify v1 && reify v2)+    evalOp Or       = \v1 v2 -> reflect (reify v1 || reify v2)+    evalOp Xor      = \v1 v2 -> reflect (reify v1 /= reify v2)+    evalOp Iff      = \v1 v2 -> reflect (reify v1 == reify v2)+    evalOp (Min  _) = error "TODO: evalOp{Min}"+    evalOp (Max  _) = error "TODO: evalOp{Max}"+    {-+    evalOp (Min  _) = \v1 v2 -> reflect (reify v1 `min` reify v2)+    evalOp (Max  _) = \v1 v2 -> reflect (reify v1 `max` reify v2)+    evalOp (Sum  _) = \v1 v2 -> reflect (reify v1 + reify v2)+    evalOp (Prod _) = \v1 v2 -> reflect (reify v1 * reify v2)+    -}+    -- HACK: this is just to have something to test. We really should reduce\/remove all this boilerplate...+    evalOp (Sum  theSemi) =+        \(WLiteral v1) (WLiteral v2) -> WLiteral $ evalSum  theSemi v1 v2+    evalOp (Prod theSemi) =+        \(WLiteral v1) (WLiteral v2) -> WLiteral $ evalProd theSemi v1 v2++    -- TODO: even if only one of the arguments is a literal, if that literal is zero\/one, then we can still partially evaluate it. (As is done in the old finally-tagless code)+    evalSum, evalProd :: HSemiring a -> Literal a -> Literal a -> Literal a+    evalSum  HSemiring_Nat  = \(LNat  n1) (LNat  n2) -> LNat  (n1 + n2)+    evalSum  HSemiring_Int  = \(LInt  i1) (LInt  i2) -> LInt  (i1 + i2)+    evalSum  HSemiring_Prob = \(LProb p1) (LProb p2) -> LProb (p1 + p2)+    evalSum  HSemiring_Real = \(LReal r1) (LReal r2) -> LReal (r1 + r2)+    evalProd HSemiring_Nat  = \(LNat  n1) (LNat  n2) -> LNat  (n1 * n2)+    evalProd HSemiring_Int  = \(LInt  i1) (LInt  i2) -> LInt  (i1 * i2)+    evalProd HSemiring_Prob = \(LProb p1) (LProb p2) -> LProb (p1 * p2)+    evalProd HSemiring_Real = \(LReal r1) (LReal r2) -> LReal (r1 * r2)+++----------------------------------------------------------------+evaluateArrayOp+    :: ( ABT Term abt, EvaluationMonad abt m p+       , typs ~ UnLCs args, args ~ LCs typs)+    => TermEvaluator abt m+    -> ArrayOp typs a+    -> SArgs abt args+    -> m (Whnf abt a)+evaluateArrayOp evaluate_ = go+    where+    go o@(Index _) = \(e1 :* e2 :* End) -> do+        w1 <- evaluate_ e1+        case w1 of+            Neutral e1' ->+                return . Neutral $ syn (ArrayOp_ o :$ e1' :* e2 :* End)+            Head_   v1  ->+                error "TODO: evaluateArrayOp{Index}{Head_}"++    go o@(Size _) = \(e1 :* End) -> do+        w1 <- evaluate_ e1+        case w1 of+            Neutral e1' -> return . Neutral $ syn (ArrayOp_ o :$ e1' :* End)+            Head_   v1  ->+                case head2array v1 of+                WAEmpty      -> return . Head_ $ WLiteral (LNat 0)+                WAArray e3 _ -> evaluate_ e3++    go (Reduce _) = \(e1 :* e2 :* e3 :* End) ->+        error "TODO: evaluateArrayOp{Reduce}"+++data ArrayHead :: ([Hakaru] -> Hakaru -> *) -> Hakaru -> * where+    WAEmpty :: ArrayHead abt a+    WAArray+        :: !(abt '[] 'HNat)+        -> !(abt '[ 'HNat] a)+        -> ArrayHead abt a++head2array :: Head abt ('HArray a) -> ArrayHead abt a+head2array (WEmpty _)     = WAEmpty+head2array (WArray e1 e2) = WAArray e1 e2+++----------------------------------------------------------------+-- TODO: maybe we should adjust 'Whnf' to have a third option for+-- closed terms of the atomic\/literal types, so that we can avoid+-- reducing them just yet. Of course, we'll have to reduce them+-- eventually, but we can leave that for the runtime evaluation or+-- Maple or whatever. These are called \"annotated\" terms in Fischer+-- et al 2008 (though they allow anything to be annotated, not just+-- closed terms of atomic type).+evaluatePrimOp+    :: forall abt m p typs args a+    .  ( ABT Term abt, EvaluationMonad abt m p+       , typs ~ UnLCs args, args ~ LCs typs)+    => TermEvaluator abt m+    -> PrimOp typs a+    -> SArgs abt args+    -> m (Whnf abt a)+evaluatePrimOp evaluate_ = go+    where+    -- HACK: we don't have any way of saying these functions haven't reduced even though it's not actually a neutral term.+    neu1 :: forall b c+        .  (abt '[] b -> abt '[] c)+        -> abt '[] b+        -> m (Whnf abt c)+    neu1 f e = (Neutral . f . fromWhnf) <$> evaluate_ e++    neu2 :: forall b c d+        .  (abt '[] b -> abt '[] c -> abt '[] d)+        -> abt '[] b+        -> abt '[] c   +        -> m (Whnf abt d)+    neu2 f e1 e2 = do e1' <- fromWhnf <$> evaluate_ e1+                      e2' <- fromWhnf <$> evaluate_ e2+                      return . Neutral $ f e1' e2'++    rr1 :: forall b b' c c'+        .  (Interp b b', Interp c c')+        => (b' -> c')+        -> (abt '[] b -> abt '[] c)+        -> abt '[] b+        -> m (Whnf abt c)+    rr1 f' f e = do+        w <- evaluate_ e+        return $+            case w of+            Neutral e' -> Neutral $ f e'+            Head_   v  -> Head_ . reflect $ f' (reify v)++    rr2 :: forall b b' c c' d d'+        .  (Interp b b', Interp c c', Interp d d')+        => (b' -> c' -> d')+        -> (abt '[] b -> abt '[] c -> abt '[] d)+        -> abt '[] b+        -> abt '[] c+        -> m (Whnf abt d)+    rr2 f' f e1 e2 = do+        w1 <- evaluate_ e1+        w2 <- evaluate_ e2+        return $+            case w1 of+            Neutral e1' -> Neutral $ f e1' (fromWhnf w2)+            Head_   v1  ->+                case w2 of+                Neutral e2' -> Neutral $ f (fromWhnf w1) e2'+                Head_   v2  -> Head_ . reflect $ f' (reify v1) (reify v2)++    primOp2_+        :: forall b c d+        .  PrimOp '[ b, c ] d -> abt '[] b -> abt '[] c -> abt '[] d+    primOp2_ o e1 e2 = syn (PrimOp_ o :$ e1 :* e2 :* End)++    -- TODO: something more efficient\/direct if we can...+    go Not  (e1 :* End)       = rr1 not  P.not  e1+    go Impl (e1 :* e2 :* End) = rr2 impl (primOp2_ Impl) e1 e2+    go Diff (e1 :* e2 :* End) = rr2 diff (primOp2_ Diff) e1 e2+    go Nand (e1 :* e2 :* End) = rr2 nand P.nand e1 e2+    go Nor  (e1 :* e2 :* End) = rr2 nor  P.nor  e1 e2++    -- HACK: we don't have a way of saying that 'Pi' (or 'Infinity',...) is in fact a head; so we're forced to call it neutral which is a lie. We should add constructor(s) to 'Head' to cover these magic constants; probably grouped together under a single constructor called something like @Constant@. Maybe should group them like that in the AST as well?+    go Pi        End               = return $ Neutral P.pi++    -- We treat trig functions as strict, thus forcing their+    -- arguments; however, to avoid fuzz issues we don't actually+    -- evaluate the trig functions.+    --+    -- HACK: we might should have some other way to make these+    -- 'Whnf' rather than calling them neutral terms; since they+    -- aren't, in fact, neutral!+    go Sin       (e1 :* End)       = neu1 P.sin   e1+    go Cos       (e1 :* End)       = neu1 P.cos   e1+    go Tan       (e1 :* End)       = neu1 P.tan   e1+    go Asin      (e1 :* End)       = neu1 P.asin  e1+    go Acos      (e1 :* End)       = neu1 P.acos  e1+    go Atan      (e1 :* End)       = neu1 P.atan  e1+    go Sinh      (e1 :* End)       = neu1 P.sinh  e1+    go Cosh      (e1 :* End)       = neu1 P.cosh  e1+    go Tanh      (e1 :* End)       = neu1 P.tanh  e1+    go Asinh     (e1 :* End)       = neu1 P.asinh e1+    go Acosh     (e1 :* End)       = neu1 P.acosh e1+    go Atanh     (e1 :* End)       = neu1 P.atanh e1++    -- TODO: deal with how we have better types for these three ops than Haskell does...+    -- go RealPow   (e1 :* e2 :* End) = rr2 (**) (P.**) e1 e2+    go RealPow   (e1 :* e2 :* End) = neu2 (P.**) e1 e2++    -- HACK: these aren't actually neutral!+    -- BUG: we should try to cancel out @(exp . log)@ and @(log . exp)@+    go Exp       (e1 :* End)       = neu1 P.exp e1+    go Log       (e1 :* End)       = neu1 P.log e1++    -- HACK: these aren't actually neutral!+    go (Infinity h)     End        =+        case h of+          HIntegrable_Nat  -> return . Neutral $ P.primOp0_ (Infinity h)+          HIntegrable_Prob -> return $ Neutral P.infinity++    go GammaFunc   (e1 :* End)            = neu1 P.gammaFunc e1+    go BetaFunc    (e1 :* e2 :* End)      = neu2 P.betaFunc  e1 e2++    go (Equal  theEq)   (e1 :* e2 :* End) = rrEqual theEq  e1 e2+    go (Less   theOrd)  (e1 :* e2 :* End) = rrLess  theOrd e1 e2+    go (NatPow theSemi) (e1 :* e2 :* End) =+        case theSemi of+        HSemiring_Nat    -> rr2 (\v1 v2 -> v1 ^ fromNatural v2) (P.^) e1 e2+        HSemiring_Int    -> rr2 (\v1 v2 -> v1 ^ fromNatural v2) (P.^) e1 e2+        HSemiring_Prob   -> rr2 (\v1 v2 -> v1 ^ fromNatural v2) (P.^) e1 e2+        HSemiring_Real   -> rr2 (\v1 v2 -> v1 ^ fromNatural v2) (P.^) e1 e2+    go (Negate theRing) (e1 :* End) =+        case theRing of+        HRing_Int        -> rr1 negate P.negate e1+        HRing_Real       -> rr1 negate P.negate e1+    go (Abs    theRing) (e1 :* End) =+        case theRing of+        HRing_Int        -> rr1 (unsafeNatural . abs) P.abs_ e1+        HRing_Real       -> rr1 (unsafeNonNegativeRational  . abs) P.abs_ e1+    go (Signum theRing) (e1 :* End) =+        case theRing of+        HRing_Int        -> rr1 signum P.signum e1+        HRing_Real       -> rr1 signum P.signum e1+    go (Recip  theFractional) (e1 :* End) =+        case theFractional of+        HFractional_Prob -> rr1 recip  P.recip  e1+        HFractional_Real -> rr1 recip  P.recip  e1+    go (NatRoot theRadical) (e1 :* e2 :* End) =+        case theRadical of+        HRadical_Prob -> neu2 (flip P.thRootOf) e1 e2+    {-+    go (NatRoot theRadical) (e1 :* e2 :* End) =+        case theRadical of+        HRadical_Prob -> rr2 natRoot (flip P.thRootOf) e1 e2+    go (Erf theContinuous) (e1 :* End) =+        case theContinuous of+        HContinuous_Prob -> rr1 erf P.erf e1+        HContinuous_Real -> rr1 erf P.erf e1+    -}+    go op _ = error $ "TODO: evaluatePrimOp{" ++ show op ++ "}"+++    rrEqual+        :: forall b. HEq b -> abt '[] b -> abt '[] b -> m (Whnf abt HBool)+    rrEqual theEq =+        case theEq of+        HEq_Nat    -> rr2 (==) (P.==)+        HEq_Int    -> rr2 (==) (P.==)+        HEq_Prob   -> rr2 (==) (P.==)+        HEq_Real   -> rr2 (==) (P.==)+        HEq_Array aEq -> error "TODO: rrEqual{HEq_Array}"+        HEq_Bool   -> rr2 (==) (P.==)+        HEq_Unit   -> rr2 (==) (P.==)+        HEq_Pair   aEq bEq ->+            \e1 e2 -> do+                w1 <- evaluate_ e1+                w2 <- evaluate_ e2+                case w1 of+                    Neutral e1' ->+                        return . Neutral+                            $ P.primOp2_ (Equal theEq) e1' (fromWhnf w2)+                    Head_   v1  ->+                        case w2 of+                        Neutral e2' ->+                            return . Neutral+                                $ P.primOp2_ (Equal theEq) (fromHead v1) e2'+                        Head_ v2 -> do+                            let (v1a, v1b) = reifyPair v1+                            let (v2a, v2b) = reifyPair v2+                            wa <- rrEqual aEq v1a v2a+                            wb <- rrEqual bEq v1b v2b+                            return $+                                case wa of+                                Neutral ea ->+                                    case wb of+                                    Neutral eb -> Neutral (ea P.&& eb)+                                    Head_   vb+                                        | reify vb  -> wa+                                        | otherwise -> Head_ $ WDatum dFalse+                                Head_ va+                                    | reify va  -> wb+                                    | otherwise -> Head_ $ WDatum dFalse++        HEq_Either aEq bEq -> error "TODO: rrEqual{HEq_Either}"++    rrLess+        :: forall b. HOrd b -> abt '[] b -> abt '[] b -> m (Whnf abt HBool)+    rrLess theOrd =+        case theOrd of+        HOrd_Nat    -> rr2 (<) (P.<)+        HOrd_Int    -> rr2 (<) (P.<)+        HOrd_Prob   -> rr2 (<) (P.<)+        HOrd_Real   -> rr2 (<) (P.<)+        HOrd_Array aOrd -> error "TODO: rrLess{HOrd_Array}"+        HOrd_Bool   -> rr2 (<) (P.<)+        HOrd_Unit   -> rr2 (<) (P.<)+        HOrd_Pair aOrd bOrd ->+            \e1 e2 -> do+                w1 <- evaluate_ e1+                w2 <- evaluate_ e2+                case w1 of+                    Neutral e1' ->+                        return . Neutral+                            $ P.primOp2_ (Less theOrd) e1' (fromWhnf w2)+                    Head_   v1  ->+                        case w2 of+                        Neutral e2' ->+                            return . Neutral+                                $ P.primOp2_ (Less theOrd) (fromHead v1) e2'+                        Head_ v2 -> do+                            let (v1a, v1b) = reifyPair v1+                            let (v2a, v2b) = reifyPair v2+                            error "TODO: rrLess{HOrd_Pair}"+                            -- BUG: The obvious recursion won't work because we need to know when the first components are equal before recursing (to implement lexicographic ordering). We really need a ternary comparison operator like 'compare'.+        HOrd_Either aOrd bOrd -> error "TODO: rrLess{HOrd_Either}"+++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Evaluation/PEvalMonad.hs view
@@ -0,0 +1,662 @@+{-# LANGUAGE CPP+           , GADTs+           , KindSignatures+           , DataKinds+           , TypeOperators+           , Rank2Types+           , BangPatterns+           , FlexibleContexts+           , MultiParamTypeClasses+           , FunctionalDependencies+           , FlexibleInstances+           , UndecidableInstances+           , EmptyCase+           , ScopedTypeVariables+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.05.24+-- |+-- Module      :  Language.Hakaru.Evaluation.PEvalMonad+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- A unified 'EvaluationMonad' for pure evaluation, expect, and+-- disintegrate.+----------------------------------------------------------------+module Language.Hakaru.Evaluation.PEvalMonad+    (+    -- * The unified 'PEval' monad+    -- ** List-based version+      ListContext(..), PAns, PEval(..)+    , runPureEval, runImpureEval, runExpectEval+    -- ** TODO: IntMap-based version+    +    -- * Operators on the disintegration monad+    -- ** The \"zero\" and \"one\"+    , bot+    --, reject+    -- ** Emitting code+    , emit+    , emitMBind+    , emitLet+    , emitLet'+    , emitUnpair+    -- TODO: emitUneither+    -- emitCaseWith+    , emit_+    , emitMBind_+    , emitGuard+    , emitWeight+    , emitFork_+    , emitSuperpose+    , choose+    ) where++import           Prelude              hiding (id, (.))+import           Control.Category     (Category(..))+#if __GLASGOW_HASKELL__ < 710+import           Data.Monoid          (Monoid(..))+import           Data.Functor         ((<$>))+import           Control.Applicative  (Applicative(..))+#endif+import qualified Data.Foldable        as F+import qualified Data.Traversable     as T+import qualified Data.List.NonEmpty   as NE+import           Control.Applicative  (Alternative(..))+import           Control.Monad        (MonadPlus(..))+import           Data.Text            (Text)+import qualified Data.Text            as Text++import Language.Hakaru.Syntax.IClasses+import Data.Number.Nat+import Language.Hakaru.Types.DataKind+import Language.Hakaru.Types.Sing    (Sing, sUnMeasure, sUnPair)+import Language.Hakaru.Syntax.AST+import Language.Hakaru.Syntax.TypeOf+import Language.Hakaru.Syntax.ABT+import Language.Hakaru.Syntax.Datum+import Language.Hakaru.Syntax.DatumABT+import qualified Language.Hakaru.Syntax.Prelude as P+import Language.Hakaru.Evaluation.Types+import Language.Hakaru.Evaluation.Lazy (reifyPair)++#ifdef __TRACE_DISINTEGRATE__+import Debug.Trace (trace)+#endif++----------------------------------------------------------------+----------------------------------------------------------------+-- | An ordered collection of statements representing the context+-- surrounding the current focus of our program transformation.+-- That is, since some transformations work from the bottom up, we+-- need to keep track of the statements we passed along the way+-- when reaching for the bottom.+--+-- The tail of the list takes scope over the head of the list. Thus,+-- the back\/end of the list is towards the top of the program,+-- whereas the front of the list is towards the bottom.+--+-- This type was formerly called @Heap@ (presumably due to the+-- 'Statement' type being called @Binding@) but that seems like a+-- misnomer to me since this really has nothing to do with allocation.+-- However, it is still like a heap inasmuch as it's a dependency+-- graph and we may wish to change the topological sorting or remove+-- \"garbage\" (subject to correctness criteria).+--+-- TODO: Figure out what to do with 'SWeight', 'SGuard', 'SStuff',+-- etc, so that we can use an @IntMap (Statement abt)@ in order to+-- speed up the lookup times in 'select'. (Assuming callers don't+-- use 'unsafePush' unsafely: we can recover the order things were+-- inserted from their 'varID' since we've freshened them all and+-- therefore their IDs are monotonic in the insertion order.)+data ListContext (abt :: [Hakaru] -> Hakaru -> *) (p :: Purity) =+    ListContext+    { nextFreshNat :: {-# UNPACK #-} !Nat+    , statements   :: [Statement abt p]+    }+++-- HACK: we can't use a type family and do @abt xs (P p a)@ because+-- of non-injectivity. So we make this a GADT instead. Because it's+-- a GADT, there's a bunch of ugly rewrapping required; but everything+-- seems to work out just fine...+data P :: Purity -> ([Hakaru] -> Hakaru -> *) -> [Hakaru] -> Hakaru -> *+    where+    PPure   :: !(abt xs a)             -> P 'Pure    abt xs a+    PImpure :: !(abt xs ('HMeasure a)) -> P 'Impure  abt xs a+    PExpect :: !(abt xs 'HProb)        -> P 'ExpectP abt xs a++unPPure :: P 'Pure abt xs a -> abt xs a+unPPure (PPure e) = e++unPImpure :: P 'Impure abt xs a -> abt xs ('HMeasure a)+unPImpure (PImpure e) = e++unPExpect :: P 'ExpectP abt xs a -> abt xs 'HProb+unPExpect (PExpect e) = e++mapPPure :: (abt xs a -> abt ys b) -> P 'Pure abt xs a -> P 'Pure abt ys b+mapPPure f (PPure e) = PPure (f e)++mapPImpure+    :: (abt xs ('HMeasure a) -> abt ys ('HMeasure b))+    -> P 'Impure abt xs a+    -> P 'Impure abt ys b+mapPImpure f (PImpure e) = PImpure (f e)++mapPExpect+    :: (abt xs 'HProb -> abt ys 'HProb)+    -> P 'ExpectP abt xs a+    -> P 'ExpectP abt ys b+mapPExpect f (PExpect e) = PExpect (f e)++mapP+    :: (forall a. abt xs a -> abt ys a)+    -> P p abt xs b+    -> P p abt ys b+mapP f (PPure   e) = PPure   $ f e+mapP f (PImpure e) = PImpure $ f e+mapP f (PExpect e) = PExpect $ f e++-- | Plug a term into a context. That is, the 'statements' of the+-- context specifies a program with a hole in it; so we plug the+-- given term into that hole, returning the complete program.+residualizeListContext+    :: forall abt p a+    .  (ABT Term abt)+    => ListContext abt p+    -> P p abt '[] a+    -> P p abt '[] a+residualizeListContext =+    -- N.B., we use a left fold because the head of the list of+    -- statements is the one closest to the hole.+    \ss e0 -> foldl (flip step) e0 (statements ss)+    where+    step+        :: Statement abt p+        -> P p abt '[] a+        -> P p abt '[] a+    step (SLet  x body _)  = mapP $ residualizeLet x body+    step (SBind x body _) = mapPImpure $ \e ->+        -- TODO: if @body@ is dirac, then treat as 'SLet'+        syn (MBind :$ fromLazy body :* bind x e :* End)+    step (SGuard xs pat scrutinee _) = mapPImpure $ \e ->+        -- TODO: avoid adding the 'PWild' branch if we know @pat@ covers the type+        syn $ Case_ (fromLazy scrutinee)+            [ Branch pat   $ binds_ xs e+            , Branch PWild $ P.reject (typeOf e)+            ]+    step (SWeight body _) = mapPImpure $ P.withWeight (fromLazy body)+    step (SStuff0    f _) = mapPExpect f+    step (SStuff1 _x f _) = mapPExpect f+++-- TODO: move this to Prelude? Is there anyone else that actually needs these smarts?+residualizeLet+    :: (ABT Term abt) => Variable a -> Lazy abt a -> abt '[] b -> abt '[] b+residualizeLet x body scope+    -- Drop unused bindings+    | not (x `memberVarSet` freeVars scope) = scope+    -- TODO: if used exactly once in @e@, then inline.+    | otherwise =+        case getLazyVariable body of+        Just y  -> subst x (var y) scope+        Nothing ->+            case getLazyLiteral body of+            Just v  -> subst x (syn $ Literal_ v) scope+            Nothing ->+                syn (Let_ :$ fromLazy body :* bind x scope :* End)++----------------------------------------------------------------+type PAns p abt m a = ListContext abt p -> m (P p abt '[] a)+++----------------------------------------------------------------+-- TODO: defunctionalize the continuation. In particular, the only+-- heap modifications we need are 'push' and a variant of 'update'+-- for finding\/replacing a binding once we have the value in hand;+-- and the only 'freshNat' modifications are to allocate new 'Nat'.+-- We could defunctionalize the second arrow too by relying on the+-- @Codensity (ReaderT e m) ~= StateT e (Codensity m)@ isomorphism,+-- which makes explicit that the only thing other than 'ListContext'+-- updates is emitting something like @[Statement]@ to serve as the+-- beginning of the final result.+--+-- | TODO: give this a better, more informative name!+newtype PEval abt p m x =+    PEval { unPEval :: forall a. (x -> PAns p abt m a) -> PAns p abt m a }+    -- == Codensity (PAns p abt m)+++-- | Run an 'Impure' computation in the 'PEval' monad, residualizing+-- out all the statements in the final evaluation context. The+-- second argument should include all the terms altered by the+-- 'PEval' expression; this is necessary to ensure proper hygiene;+-- for example(s):+--+-- > runPEval (perform e) [Some2 e]+-- > runPEval (constrainOutcome e v) [Some2 e, Some2 v]+--+-- We use 'Some2' on the inputs because it doesn't matter what their+-- type or locally-bound variables are, so we want to allow @f@ to+-- contain terms with different indices.+runImpureEval+    :: (ABT Term abt, Applicative m, F.Foldable f)+    => PEval abt 'Impure m (abt '[] a)+    -> f (Some2 abt)+    -> m (abt '[] ('HMeasure a))+runImpureEval m es =+    unPImpure <$> unPEval m c0 h0+    where+    i0      = maxNextFree es -- TODO: is maxNextFreeOrBind better here?+    h0      = ListContext i0 []+    -- TODO: we only use dirac because 'residualizeListContext'+    -- requires it to already be a measure; unfortunately this can+    -- result in an extraneous @(>>= \x -> dirac x)@ redex at the+    -- end of the program. In principle, we should be able to+    -- eliminate that redex by changing the type of+    -- 'residualizeListContext'...+    c0 e ss =+        pure+        . residualizeListContext ss+        . PImpure+        $ syn(Dirac :$ e :* End)++runPureEval+    :: (ABT Term abt, Applicative m, F.Foldable f)+    => PEval abt 'Pure m (abt '[] a)+    -> f (Some2 abt)+    -> m (abt '[] a)+runPureEval m es =+    unPPure <$> unPEval m c0 h0+    where+    i0      = maxNextFree es -- TODO: is maxNextFreeOrBind better here?+    h0      = ListContext i0 []+    c0 e ss = pure . residualizeListContext ss $ PPure e++runExpectEval+    :: (ABT Term abt, Applicative m, F.Foldable f)+    => PEval abt 'ExpectP m (abt '[] a)+    -> abt '[a] 'HProb+    -> f (Some2 abt)+    -> m (abt '[] 'HProb)+runExpectEval m f es =+    unPExpect <$> unPEval m c0 h0+    where+    i0      = nextFreeOrBind f `max` maxNextFreeOrBind es+    h0      = ListContext i0 []+    c0 e ss =+        pure+        . residualizeListContext ss+        . PExpect+        $ caseVarSyn e+            (\x -> caseBind f $ \y f' -> subst y (var x) f')+            (\_ -> syn (Let_ :$ e :* f :* End))+        -- TODO: make this smarter still, to drop the let-binding entirely if it's not used in @f@.+++instance Functor (PEval abt p m) where+    fmap f m = PEval $ \c -> unPEval m (c . f)++instance Applicative (PEval abt p m) where+    pure x    = PEval $ \c -> c x+    mf <*> mx = PEval $ \c -> unPEval mf $ \f -> unPEval mx $ \x -> c (f x)++instance Monad (PEval abt p m) where+    return   = pure+    mx >>= k = PEval $ \c -> unPEval mx $ \x -> unPEval (k x) c++instance Alternative m => Alternative (PEval abt p m) where+    empty   = PEval $ \_ _ -> empty+    m <|> n = PEval $ \c h -> unPEval m c h <|> unPEval n c h++instance Alternative m => MonadPlus (PEval abt p m) where+    mzero = empty -- aka "bot"+    mplus = (<|>) -- aka "lub"++instance (ABT Term abt) => EvaluationMonad abt (PEval abt p m) p where+    freshNat =+        PEval $ \c (ListContext i ss) ->+            c i (ListContext (i+1) ss)++    unsafePush s =+        PEval $ \c (ListContext i ss) ->+            c () (ListContext i (s:ss))++    -- N.B., the use of 'reverse' is necessary so that the order+    -- of pushing matches that of 'pushes'+    unsafePushes ss =+        PEval $ \c (ListContext i ss') ->+            c () (ListContext i (reverse ss ++ ss'))++    select x p = loop []+        where+        -- TODO: use a DList to avoid reversing inside 'unsafePushes'+        loop ss = do+            ms <- unsafePop+            case ms of+                Nothing -> do+                    unsafePushes ss+                    return Nothing+                Just s  ->+                    -- Alas, @p@ will have to recheck 'isBoundBy'+                    -- in order to grab the 'Refl' proof we erased;+                    -- but there's nothing to be done for it.+                    case x `isBoundBy` s >> p s of+                    Nothing -> loop (s:ss) -- BUG: we only want to loop if @x@ isn't bound by @s@; if it is bound but @p@ fails (e.g., because @s@ is 'Stuff1'), then we should fail/stop (thus the return type should be @2+r@ to distinguish no-match = free vs failed-match = bound-but-inalterable)+                    Just mr -> do+                        r <- mr+                        unsafePushes ss+                        return (Just r)++-- | Not exported because we only need it for defining 'select' on 'PEval'.+unsafePop :: PEval abt p m (Maybe (Statement abt p))+unsafePop =+    PEval $ \c h@(ListContext i ss) ->+        case ss of+        []    -> c Nothing  h+        s:ss' -> c (Just s) (ListContext i ss')++----------------------------------------------------------------+----------------------------------------------------------------++-- | It is impossible to satisfy the constraints, or at least we+-- give up on trying to do so. This function is identical to 'empty'+-- and 'mzero' for 'PEval'; we just give it its own name since this is+-- the name used in our papers.+--+-- TODO: add some sort of trace information so we can get a better+-- idea what caused a disintegration to fail.+bot :: (ABT Term abt, Alternative m) => PEval abt p m a+bot = empty+++{-+-- BUG: no longer typechecks after splitting 'Reject_' out from 'Superpose_'+-- | The empty measure is a solution to the constraints.+reject :: (ABT Term abt) => PEval abt p m a+reject = PEval $ \_ _ -> return . P.reject $ SMeasure sing+-}+++-- Something essentially like this function was called @insert_@+-- in the finally-tagless code.+--+-- | Emit some code that binds a variable, and return the variable+-- thus bound. The function says what to wrap the result of the+-- continuation with; i.e., what we're actually emitting.+emit+    :: (ABT Term abt, Functor m)+    => Text+    -> Sing a+    -> (forall r. P p abt '[a] r -> P p abt '[] r)+    -> PEval abt p m (Variable a)+emit hint typ f = do+    x <- freshVar hint typ+    PEval $ \c h -> (f . mapP (bind x)) <$> c x h+++-- This function was called @lift@ in the finally-tagless code.+-- | Emit an 'MBind' (i.e., \"@m >>= \x ->@\") and return the+-- variable thus bound (i.e., @x@).+emitMBind+    :: (ABT Term abt, Functor m)+    => abt '[] ('HMeasure a)+    -> PEval abt 'Impure m (Variable a)+emitMBind m =+    emit Text.empty (sUnMeasure $ typeOf m) $ \(PImpure e) ->+        PImpure $ syn (MBind :$ m :* e :* End)+++-- | A smart constructor for emitting let-bindings. If the input+-- is already a variable then we just return it; otherwise we emit+-- the let-binding. N.B., this function provides the invariant that+-- the result is in fact a variable; whereas 'emitLet'' does not.+emitLet+    :: (ABT Term abt, Functor m) => abt '[] a -> PEval abt p m (Variable a)+emitLet e =+    caseVarSyn e return $ \_ ->+        -- N.B., must use the second @($)@ here because rank-2 polymorphism+        emit Text.empty (typeOf e) $ mapP $ \m ->+            syn (Let_ :$ e :* m :* End)++-- | A smart constructor for emitting let-bindings. If the input+-- is already a variable or a literal constant, then we just return+-- it; otherwise we emit the let-binding. N.B., this function+-- provides weaker guarantees on the type of the result; if you+-- require the result to always be a variable, then see 'emitLet'+-- instead.+emitLet'+    :: (ABT Term abt, Functor m) => abt '[] a -> PEval abt p m (abt '[] a)+emitLet' e =+    caseVarSyn e (const $ return e) $ \t ->+        case t of+        Literal_ _ -> return e+        _ -> do+            -- N.B., must use the second @($)@ here because rank-2 polymorphism+            x <- emit Text.empty (typeOf e) $ mapP $ \m ->+                syn (Let_ :$ e :* m :* End)+            return (var x)++-- | A smart constructor for emitting \"unpair\". If the input+-- argument is actually a constructor then we project out the two+-- components; otherwise we emit the case-binding and return the+-- two variables.+emitUnpair+    :: (ABT Term abt, Applicative m)+    => Whnf abt (HPair a b)+    -> PEval abt p m (abt '[] a, abt '[] b)+emitUnpair (Head_   w) = return $ reifyPair w+emitUnpair (Neutral e) = do+    let (a,b) = sUnPair (typeOf e)+    x <- freshVar Text.empty a+    y <- freshVar Text.empty b+    emitUnpair_ x y e++emitUnpair_+    :: forall abt p m a b+    .  (ABT Term abt, Applicative m)+    => Variable a+    -> Variable b+    -> abt '[] (HPair a b)+    -> PEval abt p m (abt '[] a, abt '[] b)+emitUnpair_ x y = loop+    where+    done :: abt '[] (HPair a b) -> PEval abt p m (abt '[] a, abt '[] b)+    done e =+#ifdef __TRACE_DISINTEGRATE__+        trace "-- emitUnpair: done (term is not Datum_ nor Case_)" $+#endif+        PEval $ \c h ->+            mapP ( syn+            . Case_ e+            . (:[])+            . Branch (pPair PVar PVar)+            . bind x+            . bind y+            ) <$> c (var x, var y) h++    loop :: abt '[] (HPair a b) -> PEval abt p m (abt '[] a, abt '[] b)+    loop e0 =+        caseVarSyn e0 (done . var) $ \t ->+            case t of+            Datum_ d   -> do+#ifdef __TRACE_DISINTEGRATE__+                trace "-- emitUnpair: found Datum_" $ return ()+#endif+                return $ reifyPair (WDatum d)+            Case_ e bs -> do+#ifdef __TRACE_DISINTEGRATE__+                trace "-- emitUnpair: going under Case_" $ return ()+#endif+                -- TODO: we want this to duplicate the current+                -- continuation for (the evaluation of @loop@ in)+                -- all branches. So far our traces all end up+                -- returning @bot@ on the first branch, and hence+                -- @bot@ for the whole case-expression, so we can't+                -- quite tell whether it does what is intended.+                --+                -- N.B., the only 'PEval'-effects in 'applyBranch'+                -- are to freshen variables; thus this use of+                -- 'traverse' is perfectly sound.+                emitCaseWith loop e bs+            _ -> done e0+++-- TODO: emitUneither+++-- This function was called @insert_@ in the old finally-tagless code.+-- | Emit some code that doesn't bind any variables. This function+-- provides an optimisation over using 'emit' and then discarding+-- the generated variable.+emit_+    :: (ABT Term abt, Functor m)+    => (forall r. P p abt '[] r -> P p abt '[] r)+    -> PEval abt p m ()+emit_ f = PEval $ \c h -> f <$> c () h+++-- | Emit an 'MBind' that discards its result (i.e., \"@m >>@\").+-- We restrict the type of the argument to be 'HUnit' so as to avoid+-- accidentally dropping things.+emitMBind_+    :: (ABT Term abt, Functor m)+    => abt '[] ('HMeasure HUnit)+    -> PEval abt 'Impure m ()+emitMBind_ m = emit_ $ mapPImpure (m P.>>)+++-- TODO: if the argument is a value, then we can evaluate the 'P.if_' immediately rather than emitting it.+-- | Emit an assertion that the condition is true.+emitGuard+    :: (ABT Term abt, Functor m)+    => abt '[] HBool+    -> PEval abt 'Impure m ()+emitGuard b = emit_ $ mapPImpure (P.withGuard b)+    -- == emit_ $ \m -> P.if_ b m P.reject++-- TODO: if the argument is the literal 1, then we can avoid emitting anything.+emitWeight+    :: (ABT Term abt, Functor m)+    => abt '[] 'HProb+    -> PEval abt 'Impure m ()+emitWeight w = emit_ $ mapPImpure (P.withWeight w)+++-- N.B., this use of 'T.traverse' is definitely correct. It's+-- sequentializing @t [abt '[] ('HMeasure a)]@ into @[t (abt '[]+-- ('HMeasure a))]@ by chosing one of the possibilities at each+-- position in @t@. No heap\/context effects can escape to mess+-- things up. In contrast, using 'T.traverse' to sequentialize @t+-- (PEval abt a)@ as @PEval abt (t a)@ is /wrong/! Doing that would give+-- the conjunctive semantics where we have effects from one position+-- in @t@ escape to affect the other positions. This has to do with+-- the general issue in partial evaluation where we need to duplicate+-- downstream work (as we do by passing the same heap to everyone)+-- because there's no general way to combing the resulting heaps+-- for each branch.+--+-- | Run each of the elements of the traversable using the same+-- heap and continuation for each one, then pass the results to a+-- function for emitting code.+emitFork_+    :: (ABT Term abt, Applicative m, T.Traversable t)+    => (forall r. t (P p abt '[] r) -> P p abt '[] r)+    -> t (PEval abt p m a)+    -> PEval abt p m a+emitFork_ f ms =+    PEval $ \c h -> f <$> T.traverse (\m -> unPEval m c h) ms+++-- | Emit a 'Superpose_' of the alternatives, each with unit weight.+emitSuperpose+    :: (ABT Term abt, Functor m)+    => [abt '[] ('HMeasure a)]+    -> PEval abt 'Impure m (Variable a)+emitSuperpose []  = error "BUG: emitSuperpose: can't use Prelude.superpose because it'll throw an error"+emitSuperpose [e] = emitMBind e+emitSuperpose es  =+    emitMBind . P.superpose . fmap ((,) P.one) $ NE.fromList es+++-- | Emit a 'Superpose_' of the alternatives, each with unit weight.+choose+    :: (ABT Term abt, Applicative m)+    => [PEval abt 'Impure m a]+    -> PEval abt 'Impure m a+choose []  = error "BUG: choose: can't use Prelude.superpose because it'll throw an error"+choose [m] = m+choose ms  =+    emitFork_+        (PImpure . P.superpose . fmap ((,) P.one . unPImpure) . NE.fromList)+        ms+++-- | Given some function we can call on the bodies of the branches,+-- freshen all the pattern-bound variables and then run the function+-- on all the branches in parallel (i.e., with the same continuation+-- and heap) and then emit a case-analysis expression with the+-- results of the continuations as the bodies of the branches. This+-- function is useful for when we really do want to emit a 'Case_'+-- expression, rather than doing the superpose of guard patterns+-- thing that 'constrainValue' does.+--+-- N.B., this function assumes (and does not verify) that the second+-- argument is emissible. So callers must guarantee this invariant,+-- by calling 'atomize' as necessary.+--+-- TODO: capture the emissibility requirement on the second argument+-- in the types.+emitCaseWith+    :: (ABT Term abt, Applicative m)+    => (abt '[] b -> PEval abt p m r)+    -> abt '[] a+    -> [Branch a abt b]+    -> PEval abt p m r+emitCaseWith f e bs = do+    error "TODO: emitCaseWith"+{-+-- BUG: this doesn't typecheck with keeping @p@ polymorphic...+    gms <- T.for bs $ \(Branch pat body) ->+        let (vars, body') = caseBinds body+        in  (\vars' ->+                let rho = toAssocs vars (fmap11 var vars')+                in  GBranch pat vars' (f $ substs rho body')+            ) <$> freshenVars vars+    PEval $ \c h ->+        (syn . Case_ e) <$> T.for gms (\gm ->+            fromGBranch <$> T.for gm (\m ->+                unPEval m c h))+{-# INLINE emitCaseWith #-}+-}+++-- HACK: to get the one case we really need to work at least.+emitCaseWith_Impure+    :: (ABT Term abt, Applicative m)+    => (abt '[] b -> PEval abt 'Impure m r)+    -> abt '[] a+    -> [Branch a abt b]+    -> PEval abt 'Impure m r+emitCaseWith_Impure f e bs = do+    gms <- T.for bs $ \(Branch pat body) ->+        let (vars, body') = caseBinds body+        in  (\vars' ->+                let rho = toAssocs1 vars (fmap11 var vars')+                in  GBranch pat vars' (f $ substs rho body')+            ) <$> freshenVars vars+    PEval $ \c h ->+        (PImpure . syn . Case_ e) <$> T.for gms (\gm ->+            fromGBranch <$> T.for gm (\m ->+                unPImpure <$> unPEval m c h))+{-# INLINE emitCaseWith_Impure #-}+++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Evaluation/Types.hs view
@@ -0,0 +1,915 @@+{-# LANGUAGE CPP+           , GADTs+           , KindSignatures+           , DataKinds+           , TypeOperators+           , Rank2Types+           , BangPatterns+           , FlexibleContexts+           , MultiParamTypeClasses+           , FunctionalDependencies+           , FlexibleInstances+           , UndecidableInstances+           , EmptyCase+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.04.28+-- |+-- Module      :  Language.Hakaru.Evaluation.Types+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- The data types for "Language.Hakaru.Evaluation.Lazy"+--+-- BUG: completely gave up on structure sharing. Need to add that back in.+--+-- TODO: once we figure out the exact API\/type of 'evaluate' and+-- can separate it from Disintegrate.hs vs its other clients (i.e.,+-- Sample.hs and Expect.hs), this file will prolly be broken up+-- into Lazy.hs itself vs Disintegrate.hs+----------------------------------------------------------------+module Language.Hakaru.Evaluation.Types+    (+    -- * Terms in particular known forms\/formats+      Head(..), fromHead, toHead, viewHeadDatum+    , Whnf(..), fromWhnf, toWhnf, caseWhnf, viewWhnfDatum+    , Lazy(..), fromLazy, caseLazy+    , getLazyVariable, isLazyVariable+    , getLazyLiteral,  isLazyLiteral++    -- * The monad for partial evaluation+    , Purity(..), Statement(..), statementVars, isBoundBy+    , Index, indVar, indSize+#ifdef __TRACE_DISINTEGRATE__+    , ppList+    , ppInds+    , ppStatement+    , pretty_Statements+    , pretty_Statements_withTerm+    , prettyAssocs+#endif+    , EvaluationMonad(..)+    , freshVar+    , freshenVar+    , Hint(..), freshVars+    , freshenVars+    , freshInd+    {- TODO: should we expose these?+    , freshenStatement+    , push_+    -}+    , push+    , pushes+    ) where++import           Prelude              hiding (id, (.))+import           Control.Category     (Category(..))+#if __GLASGOW_HASKELL__ < 710+import           Data.Monoid          (Monoid(..))+import           Data.Functor         ((<$>))+import           Control.Applicative  (Applicative(..))+#endif+import           Control.Arrow        ((***))+import qualified Data.Foldable        as F+import           Data.List.NonEmpty   (NonEmpty(..))+import qualified Data.Text            as T+import           Data.Text            (Text)+import           Data.Proxy           (KProxy(..))++import Language.Hakaru.Syntax.IClasses+import Data.Number.Nat+import Language.Hakaru.Types.DataKind+import Language.Hakaru.Types.Sing    (Sing(..))+import Language.Hakaru.Types.Coercion+import Language.Hakaru.Syntax.AST+import Language.Hakaru.Syntax.Datum+import Language.Hakaru.Syntax.AST.Eq (alphaEq)+-- import Language.Hakaru.Syntax.TypeOf+import Language.Hakaru.Syntax.ABT+import qualified Language.Hakaru.Syntax.Prelude as P++#ifdef __TRACE_DISINTEGRATE__+import qualified Text.PrettyPrint     as PP+import Language.Hakaru.Pretty.Haskell+#endif++----------------------------------------------------------------+----------------------------------------------------------------+-- N.B., when putting things into the context, be sure to freshen+-- the variables as if we were allocating a new location on the+-- heap.+--+-- For simplicity we don't actually distinguish between "variables"+-- and "locations". In the old finally-tagless code we had an @s@+-- parameter like the 'ST' monad does in order to keep track of+-- which heap things belong to. But since we might have nested+-- disintegration, and thus nested heaps, doing that means we'd+-- have to do some sort of De Bruijn numbering in the @s@ parameter+-- in order to keep track of the nested regions; and that's just+-- too much work to bother with.+++-- TODO: for forward disintegration (which is not just partial evaluation) we really do mean proper HNFs not just WHNFs. This falls out from our needing to guarantee that heap-bound variables can't possibly escape; whence the assumption that the result of forward disintegration contains no heap-bound variables.+--+-- TODO: is there a way to integrate this into the actual 'Term'+-- definition in order to reduce repetition?+--+-- HACK: can't use \"H\" as the prefix because that clashes with+-- the Hakaru datakind+--+-- | A \"weak-head\" for the sake of 'Whnf'. N.B., this doesn't+-- exactly correlate with the usual notion of \"weak-head\"; in+-- particular we keep track of type annotations and coercions, and+-- don't reduce integration\/summation. So really we should use+-- some other name for 'Whnf'...+data Head :: ([Hakaru] -> Hakaru -> *) -> Hakaru -> * where+    -- Simple heads (aka, the usual stuff)+    WLiteral :: !(Literal a) -> Head abt a+    -- BUG: even though the 'Datum' type has a single constructor, we get a warning about not being able to UNPACK it in 'WDatum'... wtf?+    WDatum :: !(Datum (abt '[]) (HData' t)) -> Head abt (HData' t)+    WEmpty :: !(Sing ('HArray a)) -> Head abt ('HArray a)+    WArray :: !(abt '[] 'HNat) -> !(abt '[ 'HNat] a) -> Head abt ('HArray a)+    WLam   :: !(abt '[ a ] b) -> Head abt (a ':-> b)++    -- Measure heads (N.B., not simply @abt '[] ('HMeasure _)@)+    WMeasureOp+        :: (typs ~ UnLCs args, args ~ LCs typs)+        => !(MeasureOp typs a)+        -> !(SArgs abt args)+        -> Head abt ('HMeasure a)+    WDirac :: !(abt '[] a) -> Head abt ('HMeasure a)+    WMBind+        :: !(abt '[] ('HMeasure a))+        -> !(abt '[ a ] ('HMeasure b))+        -> Head abt ('HMeasure b)+    WPlate+        :: !(abt '[] 'HNat)+        -> !(abt '[ 'HNat ] ('HMeasure a))+        -> Head abt ('HMeasure ('HArray a))+    WChain+        :: !(abt '[] 'HNat)+        -> !(abt '[] s)+        -> !(abt '[ s ] ('HMeasure (HPair a s)))+        -> Head abt ('HMeasure (HPair ('HArray a) s))+    WSuperpose+        :: !(NonEmpty (abt '[] 'HProb, abt '[] ('HMeasure a)))+        -> Head abt ('HMeasure a)+    WReject+        :: !(Sing ('HMeasure a)) -> Head abt ('HMeasure a)++    -- Type coercion stuff. These are transparent re head-ness; that is, they behave more like HNF than WHNF.+    -- TODO: we prolly don't actually want\/need the coercion variants... we'd lose some proven-guarantees about cancellation, but everything should work just fine. The one issue that remains is if we have coercion of 'WIntegrate' or 'WSummate', since without the 'WCoerceTo'\/'WUnsafeFrom' constructors we'd be forced to call the coercion of an integration \"neutral\"--- even though it's not actually a neutral term!+    WCoerceTo   :: !(Coercion a b) -> !(Head abt a) -> Head abt b+    WUnsafeFrom :: !(Coercion a b) -> !(Head abt b) -> Head abt a++    -- Other funky stuff+    WIntegrate+        :: !(abt '[] 'HReal)+        -> !(abt '[] 'HReal)+        -> !(abt '[ 'HReal ] 'HProb)+        -> Head abt 'HProb+    -- WSummate+    --     :: !(abt '[] 'HReal)+    --     -> !(abt '[] 'HReal)+    --     -> !(abt '[ 'HInt ] 'HProb)+    --     -> Head abt 'HProb++    -- Quasi-/semi-/demi-/pseudo- normal form stuff+    {-+    NaryOp_ :: !(NaryOp a) -> !(Seq (abt '[] a)) -> Term abt a+    PrimOp_+        :: (typs ~ UnLCs args, args ~ LCs typs)+        => !(PrimOp typs a) -> SCon args a+    -- N.B., not 'ArrayOp_'+    -}+++-- | Forget that something is a head.+fromHead :: (ABT Term abt) => Head abt a -> abt '[] a+fromHead (WLiteral    v)        = syn (Literal_ v)+fromHead (WDatum      d)        = syn (Datum_ d)+fromHead (WEmpty      typ)      = syn (Empty_ typ)+fromHead (WArray      e1 e2)    = syn (Array_ e1 e2)+fromHead (WLam        e1)       = syn (Lam_ :$ e1 :* End)+fromHead (WMeasureOp  o  es)    = syn (MeasureOp_ o :$ es)+fromHead (WDirac      e1)       = syn (Dirac :$ e1 :* End)+fromHead (WMBind      e1 e2)    = syn (MBind :$ e1 :* e2 :* End)+fromHead (WPlate      e1 e2)    = syn (Plate :$ e1 :* e2 :* End)+fromHead (WChain      e1 e2 e3) = syn (Chain :$ e1 :* e2 :* e3 :* End)+fromHead (WSuperpose  pes)      = syn (Superpose_ pes)+fromHead (WReject     typ)      = syn (Reject_ typ)+fromHead (WCoerceTo   c e1)     = syn (CoerceTo_   c :$ fromHead e1 :* End)+fromHead (WUnsafeFrom c e1)     = syn (UnsafeFrom_ c :$ fromHead e1 :* End)+fromHead (WIntegrate  e1 e2 e3) = syn (Integrate :$ e1 :* e2 :* e3 :* End)+--fromHead (WSummate    e1 e2 e3) = syn (Summate   :$ e1 :* e2 :* e3 :* End)+++-- | Identify terms which are already heads.+toHead :: (ABT Term abt) => abt '[] a -> Maybe (Head abt a)+toHead e =+    caseVarSyn e (const Nothing) $ \t ->+        case t of+        Literal_     v                      -> Just $ WLiteral   v+        Datum_       d                      -> Just $ WDatum     d+        Empty_       typ                    -> Just $ WEmpty     typ+        Array_       e1     e2              -> Just $ WArray     e1 e2+        Lam_      :$ e1  :* End             -> Just $ WLam       e1+        MeasureOp_   o   :$ es              -> Just $ WMeasureOp o  es+        Dirac     :$ e1  :* End             -> Just $ WDirac     e1+        MBind     :$ e1  :* e2 :* End       -> Just $ WMBind     e1 e2+        Plate     :$ e1  :* e2 :* End       -> Just $ WPlate     e1 e2+        Chain     :$ e1  :* e2 :* e3 :* End -> Just $ WChain     e1 e2 e3 +        Superpose_   pes                    -> Just $ WSuperpose pes+        CoerceTo_    c   :$ e1 :* End       -> WCoerceTo   c <$> toHead e1+        UnsafeFrom_  c   :$ e1 :* End       -> WUnsafeFrom c <$> toHead e1+        Integrate :$ e1  :* e2 :* e3 :* End -> Just $ WIntegrate e1 e2 e3+        --Summate   :$ e1  :* e2 :* e3 :* End -> Just $ WSummate   e1 e2 e3+        _ -> Nothing++instance Functor21 Head where+    fmap21 _ (WLiteral    v)        = WLiteral v+    fmap21 f (WDatum      d)        = WDatum (fmap11 f d)+    fmap21 _ (WEmpty      typ)      = WEmpty typ+    fmap21 f (WArray      e1 e2)    = WArray (f e1) (f e2)+    fmap21 f (WLam        e1)       = WLam (f e1)+    fmap21 f (WMeasureOp  o  es)    = WMeasureOp o (fmap21 f es)+    fmap21 f (WDirac      e1)       = WDirac (f e1)+    fmap21 f (WMBind      e1 e2)    = WMBind (f e1) (f e2)+    fmap21 f (WPlate      e1 e2)    = WPlate (f e1) (f e2)+    fmap21 f (WChain      e1 e2 e3) = WChain (f e1) (f e2) (f e3)+    fmap21 f (WSuperpose  pes)      = WSuperpose (fmap (f *** f) pes)+    fmap21 _ (WReject     typ)      = WReject typ+    fmap21 f (WCoerceTo   c e1)     = WCoerceTo   c (fmap21 f e1)+    fmap21 f (WUnsafeFrom c e1)     = WUnsafeFrom c (fmap21 f e1)+    fmap21 f (WIntegrate  e1 e2 e3) = WIntegrate (f e1) (f e2) (f e3)+    --fmap21 f (WSummate    e1 e2 e3) = WSummate   (f e1) (f e2) (f e3)++instance Foldable21 Head where+    foldMap21 _ (WLiteral    _)        = mempty+    foldMap21 f (WDatum      d)        = foldMap11 f d+    foldMap21 _ (WEmpty      _)        = mempty+    foldMap21 f (WArray      e1 e2)    = f e1 `mappend` f e2+    foldMap21 f (WLam        e1)       = f e1+    foldMap21 f (WMeasureOp  _  es)    = foldMap21 f es+    foldMap21 f (WDirac      e1)       = f e1+    foldMap21 f (WMBind      e1 e2)    = f e1 `mappend` f e2+    foldMap21 f (WPlate      e1 e2)    = f e1 `mappend` f e2+    foldMap21 f (WChain      e1 e2 e3) = f e1 `mappend` f e2 `mappend` f e3+    foldMap21 f (WSuperpose  pes)      = foldMapPairs f pes+    foldMap21 _ (WReject     _)        = mempty+    foldMap21 f (WCoerceTo   _ e1)     = foldMap21 f e1+    foldMap21 f (WUnsafeFrom _ e1)     = foldMap21 f e1+    foldMap21 f (WIntegrate  e1 e2 e3) = f e1 `mappend` f e2 `mappend` f e3+    --foldMap21 f (WSummate    e1 e2 e3) = f e1 `mappend` f e2 `mappend` f e3++instance Traversable21 Head where+    traverse21 _ (WLiteral    v)        = pure $ WLiteral v+    traverse21 f (WDatum      d)        = WDatum <$> traverse11 f d+    traverse21 _ (WEmpty      typ)      = pure $ WEmpty typ+    traverse21 f (WArray      e1 e2)    = WArray <$> f e1 <*> f e2+    traverse21 f (WLam        e1)       = WLam <$> f e1+    traverse21 f (WMeasureOp  o  es)    = WMeasureOp o <$> traverse21 f es+    traverse21 f (WDirac      e1)       = WDirac <$> f e1+    traverse21 f (WMBind      e1 e2)    = WMBind <$> f e1 <*> f e2+    traverse21 f (WPlate      e1 e2)    = WPlate <$> f e1 <*> f e2+    traverse21 f (WChain      e1 e2 e3) = WChain <$> f e1 <*> f e2 <*> f e3+    traverse21 f (WSuperpose  pes)      = WSuperpose <$> traversePairs f pes+    traverse21 _ (WReject     typ)      = pure $ WReject typ+    traverse21 f (WCoerceTo   c e1)     = WCoerceTo   c <$> traverse21 f e1+    traverse21 f (WUnsafeFrom c e1)     = WUnsafeFrom c <$> traverse21 f e1+    traverse21 f (WIntegrate  e1 e2 e3) = WIntegrate <$> f e1 <*> f e2 <*> f e3+    --traverse21 f (WSummate    e1 e2 e3) = WSummate   <$> f e1 <*> f e2 <*> f e3+++----------------------------------------------------------------+-- BUG: haddock doesn't like annotations on GADT constructors. So+-- here we'll avoid using the GADT syntax, even though it'd make+-- the data type declaration prettier\/cleaner.+-- <https://github.com/hakaru-dev/hakaru/issues/6>++-- | Weak head-normal forms are either heads or neutral terms (i.e.,+-- a term whose reduction is blocked on some free variable).+data Whnf (abt :: [Hakaru] -> Hakaru -> *) (a :: Hakaru)+    = Head_   !(Head abt a)+    | Neutral !(abt '[] a)+    -- TODO: would it be helpful to track which variable it's blocked+    -- on? To do so we'd need 'GotStuck' to return that info...+    --+    -- TODO: is there some /clean/ way to ensure that the neutral term is exactly a chain of blocked redexes? That is, we want to be able to pull out neutral 'Case_' terms; so we want to make sure they're not wrapped in let-bindings, coercions, etc.++-- | Forget that something is a WHNF.+fromWhnf :: (ABT Term abt) => Whnf abt a -> abt '[] a+fromWhnf (Head_   e) = fromHead e+fromWhnf (Neutral e) = e+++-- | Identify terms which are already heads. N.B., we make no attempt+-- to identify neutral terms, we just massage the type of 'toHead'.+toWhnf :: (ABT Term abt) => abt '[] a -> Maybe (Whnf abt a)+toWhnf e = Head_ <$> toHead e++-- | Case analysis on 'Whnf' as a combinator.+caseWhnf :: Whnf abt a -> (Head abt a -> r) -> (abt '[] a -> r) -> r+caseWhnf (Head_   e) k _ = k e+caseWhnf (Neutral e) _ k = k e+++instance Functor21 Whnf where+    fmap21 f (Head_   v) = Head_ (fmap21 f v)+    fmap21 f (Neutral e) = Neutral (f e)++instance Foldable21 Whnf where+    foldMap21 f (Head_   v) = foldMap21 f v+    foldMap21 f (Neutral e) = f e++instance Traversable21 Whnf where+    traverse21 f (Head_   v) = Head_ <$> traverse21 f v+    traverse21 f (Neutral e) = Neutral <$> f e+++-- | Given some WHNF, try to extract a 'Datum' from it.+viewWhnfDatum+    :: (ABT Term abt)+    => Whnf abt (HData' t)+    -> Maybe (Datum (abt '[]) (HData' t))+viewWhnfDatum (Head_   v) = Just $ viewHeadDatum v+viewWhnfDatum (Neutral _) = Nothing+    -- N.B., we always return Nothing for 'Neutral' terms because of+    -- what 'Neutral' is supposed to mean. If we wanted to be paranoid+    -- then we could use the following code to throw an error if+    -- we're given a \"neutral\" term which is in fact a head+    -- (because that indicates an error in our logic of constructing+    -- 'Neutral' values):+    {-+    caseVarSyn e (const Nothing) $ \t ->+        case t of+        Datum_ d -> error "bad \"neutral\" value!"+        _        -> Nothing+    -}++viewHeadDatum+    :: (ABT Term abt)+    => Head abt (HData' t)+    -> Datum (abt '[]) (HData' t)+viewHeadDatum (WDatum d) = d+viewHeadDatum _          = error "viewHeadDatum: the impossible happened"+++-- Alas, to avoid the orphanage, this instance must live here rather than in Lazy.hs where it more conceptually belongs.+-- TODO: better unify the two cases of Whnf+-- HACK: this instance requires -XUndecidableInstances+instance (ABT Term abt) => Coerce (Whnf abt) where+    coerceTo c w =+        case w of+        Neutral e ->+            Neutral . maybe (P.coerceTo_ c e) id+                $ caseVarSyn e (const Nothing) $ \t ->+                    case t of+                    -- BUG: literals should never be neutral in the first place; but even if we got one, we shouldn't call it neutral after coercing it.+                    Literal_ x          -> Just $ P.literal_ (coerceTo c x)+                    -- UnsafeFrom_ c' :$ es' -> TODO: cancellation+                    CoerceTo_ c' :$ es' ->+                        case es' of+                        e' :* End -> Just $ P.coerceTo_ (c . c') e'+                        _ -> error "coerceTo@Whnf: the impossible happened"+                    _ -> Nothing+        Head_ v ->+            case v of+            WLiteral x      -> Head_ $ WLiteral (coerceTo c x)+            -- WUnsafeFrom c' v' -> TODO: cancellation+            WCoerceTo c' v' -> Head_ $ WCoerceTo (c . c') v'+            _               -> Head_ $ WCoerceTo c v+    +    coerceFrom c w =+        case w of+        Neutral e ->+            Neutral . maybe (P.unsafeFrom_ c e) id+                $ caseVarSyn e (const Nothing) $ \t ->+                    case t of+                    -- BUG: literals should never be neutral in the first place; but even if we got one, we shouldn't call it neutral after coercing it.+                    Literal_ x -> Just $ P.literal_ (coerceFrom c x)+                    -- CoerceTo_ c' :$ es' -> TODO: cancellation+                    UnsafeFrom_ c' :$ es' ->+                        case es' of+                        e' :* End -> Just $ P.unsafeFrom_ (c' . c) e'+                        _ -> error "unsafeFrom@Whnf: the impossible happened"+                    _ -> Nothing+        Head_ v ->+            case v of+            WLiteral x        -> Head_ $ WLiteral (coerceFrom c x)+            -- WCoerceTo c' v' -> TODO: cancellation+            WUnsafeFrom c' v' -> Head_ $ WUnsafeFrom (c' . c) v'+            _                 -> Head_ $ WUnsafeFrom c v+++----------------------------------------------------------------+-- BUG: haddock doesn't like annotations on GADT constructors. So+-- here we'll avoid using the GADT syntax, even though it'd make+-- the data type declaration prettier\/cleaner.+-- <https://github.com/hakaru-dev/hakaru/issues/6>++-- | Lazy terms are either thunks (i.e., any term, which we may+-- decide to evaluate later) or are already evaluated to WHNF.+data Lazy (abt :: [Hakaru] -> Hakaru -> *) (a :: Hakaru)+    = Whnf_ !(Whnf abt a)+    | Thunk !(abt '[] a)++-- | Forget whether a term has been evaluated to WHNF or not.+fromLazy :: (ABT Term abt) => Lazy abt a -> abt '[] a+fromLazy (Whnf_ e) = fromWhnf e+fromLazy (Thunk e) = e++-- | Case analysis on 'Lazy' as a combinator.+caseLazy :: Lazy abt a -> (Whnf abt a -> r) -> (abt '[] a -> r) -> r+caseLazy (Whnf_ e) k _ = k e+caseLazy (Thunk e) _ k = k e++instance Functor21 Lazy where+    fmap21 f (Whnf_ v) = Whnf_ (fmap21 f v)+    fmap21 f (Thunk e) = Thunk (f e)++instance Foldable21 Lazy where+    foldMap21 f (Whnf_ v) = foldMap21 f v+    foldMap21 f (Thunk e) = f e++instance Traversable21 Lazy where+    traverse21 f (Whnf_ v) = Whnf_ <$> traverse21 f v+    traverse21 f (Thunk e) = Thunk <$> f e+++-- | Is the lazy value a variable?+getLazyVariable :: (ABT Term abt) => Lazy abt a -> Maybe (Variable a)+getLazyVariable e =+    case e of+    Whnf_ (Head_   _)  -> Nothing+    Whnf_ (Neutral e') -> caseVarSyn e' Just (const Nothing)+    Thunk e'           -> caseVarSyn e' Just (const Nothing)++-- | Boolean-blind variant of 'getLazyVariable'+isLazyVariable :: (ABT Term abt) => Lazy abt a -> Bool+isLazyVariable = maybe False (const True) . getLazyVariable+++-- | Is the lazy value a literal?+getLazyLiteral :: (ABT Term abt) => Lazy abt a -> Maybe (Literal a)+getLazyLiteral e =+    case e of+    Whnf_ (Head_ (WLiteral v)) -> Just v+    Whnf_ _                    -> Nothing -- by construction+    Thunk e' ->+        caseVarSyn e' (const Nothing) $ \t ->+            case t of+            Literal_ v -> Just v+            _          -> Nothing++-- | Boolean-blind variant of 'getLazyLiteral'+isLazyLiteral :: (ABT Term abt) => Lazy abt a -> Bool+isLazyLiteral = maybe False (const True) . getLazyLiteral++----------------------------------------------------------------++-- | A kind for indexing 'Statement' to know whether the statement+-- is pure (and thus can be evaluated in any ambient monad) vs+-- impure (i.e., must be evaluated in the 'HMeasure' monad).+--+-- TODO: better names!+data Purity = Pure | Impure | ExpectP+    deriving (Eq, Read, Show)++data Index ast = Ind (Variable 'HNat) (ast 'HNat)++instance (ABT Term abt) => Eq (Index (abt '[])) where+    Ind i1 s1 == Ind i2 s2 = i1 == i2 && (alphaEq s1 s2)++instance (ABT Term abt) => Ord (Index (abt '[])) where+    compare (Ind i _) (Ind j _) = compare i j -- TODO check this++indVar :: Index ast -> Variable 'HNat+indVar (Ind v _ ) = v++indSize :: Index ast -> ast 'HNat+indSize (Ind _ a) = a++-- | A single statement in some ambient monad (specified by the @p@+-- type index). In particular, note that the the first argument to+-- 'MBind' (or 'Let_') together with the variable bound in the+-- second argument forms the \"statement\" (leaving out the body+-- of the second argument, which may be part of a following statement).+-- In addition to these binding constructs, we also include a few+-- non-binding statements like 'SWeight'.+--+-- The semantics of this type are as follows. Let @ss :: [Statement+-- abt p]@ be a sequence of statements. We have @Γ@: the collection+-- of all free variables that occur in the term expressions in @ss@,+-- viewed as a measureable space (namely the product of the measureable+-- spaces for each variable). And we have @Δ@: the collection of+-- all variables bound by the statements in @ss@, also viewed as a+-- measurable space. The semantic interpretation of @ss@ is a+-- measurable function of type @Γ ':-> M Δ@ where @M@ is either+-- @HMeasure@ (if @p ~ 'Impure@) or @Identity@ (if @p ~ 'Pure@).+data Statement :: ([Hakaru] -> Hakaru -> *) -> Purity -> * where+    -- BUG: haddock doesn't like annotations on GADT constructors. So we can't make the constructor descriptions below available to Haddock.+    -- <https://github.com/hakaru-dev/hakaru/issues/6>+    +    -- A variable bound by 'MBind' to a measure expression.+    SBind+        :: forall abt (a :: Hakaru)+        .  {-# UNPACK #-} !(Variable a)+        -> !(Lazy abt ('HMeasure a))+        -> [Index (abt '[])]+        -> Statement abt 'Impure++    -- A variable bound by 'Let_' to an expression.+    SLet+        :: forall abt p (a :: Hakaru)+        .  {-# UNPACK #-} !(Variable a)+        -> !(Lazy abt a)+        -> [Index (abt '[])]+        -> Statement abt p+++    -- A weight; i.e., the first component of each argument to+    -- 'Superpose_'. This is a statement just so that we can avoid+    -- needing to atomize the weight itself.+    SWeight+        :: forall abt+        .  !(Lazy abt 'HProb)+        -> [Index (abt '[])]+        -> Statement abt 'Impure++    -- A monadic guard statement. If the scrutinee matches the+    -- pattern, then we bind the variables as usual; otherwise, we+    -- return the empty measure. N.B., this statement type is only+    -- for capturing constraints that some pattern matches /in a/+    -- /monadic context/. In pure contexts we should be able to+    -- handle case analysis without putting anything onto the heap.+    SGuard+        :: forall abt (xs :: [Hakaru]) (a :: Hakaru)+        .  !(List1 Variable xs)+        -> !(Pattern xs a)+        -> !(Lazy abt a)+        -> [Index (abt '[])]+        -> Statement abt 'Impure++    -- Some arbitrary pure code. This is a statement just so that we can avoid needing to atomize the stuff in the pure code.+    --+    -- TODO: real names for these.+    -- TODO: generalize to use a 'VarSet' so we can collapse these+    -- TODO: defunctionalize? These break pretty printing...+    SStuff0+        :: forall abt+        .  (abt '[] 'HProb -> abt '[] 'HProb)+        -> [Index (abt '[])]+        -> Statement abt 'ExpectP+    SStuff1+        :: forall abt (a :: Hakaru)+        . {-# UNPACK #-} !(Variable a)+        -> (abt '[] 'HProb -> abt '[] 'HProb)+        -> [Index (abt '[])]+        -> Statement abt 'ExpectP+++statementVars :: Statement abt p -> VarSet ('KProxy :: KProxy Hakaru)+statementVars (SBind x _ _)     = singletonVarSet x+statementVars (SLet  x _ _)     = singletonVarSet x+statementVars (SWeight _ _)     = emptyVarSet+statementVars (SGuard xs _ _ _) = toVarSet1 xs+statementVars (SStuff0   _ _)   = emptyVarSet+statementVars (SStuff1 x _ _)   = singletonVarSet x    ++-- | Is the variable bound by the statement?+--+-- We return @Maybe ()@ rather than @Bool@ because in our primary+-- use case we're already in the @Maybe@ monad and so it's easier+-- to just stick with that. If we find other situations where we'd+-- really rather have the @Bool@, then we can easily change things+-- and use some @boolToMaybe@ function to do the coercion wherever+-- needed.+isBoundBy :: Variable (a :: Hakaru) -> Statement abt p -> Maybe ()+x `isBoundBy` SBind  y  _ _   = const () <$> varEq x y+x `isBoundBy` SLet   y  _ _   = const () <$> varEq x y+_ `isBoundBy` SWeight   _ _   = Nothing+x `isBoundBy` SGuard ys _ _ _ =+    if memberVarSet x (toVarSet1 ys) -- TODO: just check membership directly, rather than going through VarSet+    then Just ()+    else Nothing+_ `isBoundBy` SStuff0   _ _   = Nothing+x `isBoundBy` SStuff1 y _ _   = const () <$> varEq x y+++-- TODO: remove this CPP guard, provided we don't end up with a cyclic dependency...+#ifdef __TRACE_DISINTEGRATE__+instance (ABT Term abt) => Pretty (Whnf abt) where+    prettyPrec_ p (Head_   w) = ppApply1 p "Head_" (fromHead w) -- HACK+    prettyPrec_ p (Neutral e) = ppApply1 p "Neutral" e++instance (ABT Term abt) => Pretty (Lazy abt) where+    prettyPrec_ p (Whnf_ w) = ppFun p "Whnf_" [PP.sep (prettyPrec_ 11 w)]+    prettyPrec_ p (Thunk e) = ppApply1 p "Thunk" e++ppApply1 :: (ABT Term abt) => Int -> String -> abt '[] a -> [PP.Doc]+ppApply1 p f e1 =+    let d = PP.text f PP.<+> PP.nest (1 + length f) (prettyPrec 11 e1)+    in [if p > 9 then PP.parens (PP.nest 1 d) else d]++ppFun :: Int -> String -> [PP.Doc] -> [PP.Doc]+ppFun _ f [] = [PP.text f]+ppFun p f ds =+    parens (p > 9) [PP.text f PP.<+> PP.nest (1 + length f) (PP.sep ds)]++parens :: Bool -> [PP.Doc] -> [PP.Doc]+parens True  ds = [PP.parens (PP.nest 1 (PP.sep ds))]+parens False ds = ds++ppList :: [PP.Doc] -> PP.Doc+ppList = PP.sep . (:[]) . PP.brackets . PP.nest 1 . PP.fsep . PP.punctuate PP.comma++ppInds :: (ABT Term abt) => [Index (abt '[])] -> PP.Doc+ppInds = ppList . map (ppVariable . indVar)++ppStatement :: (ABT Term abt) => Int -> Statement abt p -> PP.Doc+ppStatement p s =+    case s of+    SBind x e inds ->+        PP.sep $ ppFun p "SBind"+            [ ppVariable x+            , PP.sep $ prettyPrec_ 11 e+            , ppInds inds+            ]+    SLet x e inds ->+        PP.sep $ ppFun p "SLet"+            [ ppVariable x+            , PP.sep $ prettyPrec_ 11 e+            , ppInds inds+            ]+    SWeight e inds ->+        PP.sep $ ppFun p "SWeight"+            [ PP.sep $ prettyPrec_ 11 e+            , ppInds inds+            ]+    SGuard xs pat e inds ->+        PP.sep $ ppFun p "SGuard"+            [ PP.sep $ ppVariables xs+            , PP.sep $ prettyPrec_ 11 pat+            , PP.sep $ prettyPrec_ 11 e+            , ppInds inds+            ]+    SStuff0   _ _ ->+        PP.sep $ ppFun p "SStuff0"+            [ PP.text "TODO: ppStatement{SStuff0}"+            ]+    SStuff1 _ _ _ ->+        PP.sep $ ppFun p "SStuff1"+            [ PP.text "TODO: ppStatement{SStuff1}"+            ]++pretty_Statements :: (ABT Term abt) => [Statement abt p] -> PP.Doc+pretty_Statements []     = PP.text "[]"+pretty_Statements (s:ss) =+    foldl+        (\d s' -> d PP.$+$ PP.comma PP.<+> ppStatement 0 s')+        (PP.text "[" PP.<+> ppStatement 0 s)+        ss+    PP.$+$ PP.text "]"++pretty_Statements_withTerm+    :: (ABT Term abt) => [Statement abt p] -> abt '[] a -> PP.Doc+pretty_Statements_withTerm ss e =+    pretty_Statements ss PP.$+$ pretty e++prettyAssocs+    :: (ABT Term abt)+    => Assocs (abt '[])+    -> PP.Doc+prettyAssocs a = PP.vcat $ map go (fromAssocs a)+  where go (Assoc x e) = ppVariable x PP.<+>+                         PP.text "->" PP.<+>+                         pretty e+                                +#endif++----------------------------------------------------------------+-- | This class captures the monadic operations needed by the+-- 'evaluate' function in "Language.Hakaru.Lazy".+class (Functor m, Applicative m, Monad m, ABT Term abt)+    => EvaluationMonad abt m p | m -> abt p+    where+    -- TODO: should we have a *method* for arbitrarily incrementing the stored 'nextFreshNat'; or should we only rely on it being initialized correctly? Beware correctness issues about updating the lower bound after having called 'freshNat'...++    -- | Return a fresh natural number. That is, a number which is+    -- not the 'varID' of any free variable in the expressions of+    -- interest, and isn't a number we've returned previously.+    freshNat :: m Nat+++    -- | Internal function for renaming the variables bound by a+    -- statement. We return the renamed statement along with a substitution+    -- for mapping the old variable names to their new variable names.+    freshenStatement+        :: Statement abt p+        -> m (Statement abt p, Assocs (Variable :: Hakaru -> *))+    freshenStatement s =+        case s of+          SWeight _ _    -> return (s, mempty)+          SBind x body i -> do+               x' <- freshenVar x+               return (SBind x' body i, singletonAssocs x x')+          SLet  x body i -> do+               x' <- freshenVar x+               return (SLet x' body i, singletonAssocs x x')+          SGuard xs pat scrutinee i -> do+               xs' <- freshenVars xs+               return (SGuard xs' pat scrutinee i, toAssocs1 xs xs')+          SStuff0   _ _ -> return (s, mempty)+          SStuff1 x f i -> do+               x' <- freshenVar x+               return (SStuff1 x' f i, singletonAssocs x x')+++    -- | Returns the current Indices. Currently, this is only+    -- applicable to the Disintegration Monad, but could be+    -- relevant as other partial evaluators begin to handle+    -- Plate and Array+    getIndices :: m [Index (abt '[])]+    getIndices =  return []++    -- | Add a statement to the top of the context. This is unsafe+    -- because it may allow confusion between variables with the+    -- same name but different scopes (thus, may allow variable+    -- capture). Prefer using 'push_', 'push', or 'pushes'.+    unsafePush :: Statement abt p -> m ()++    -- | Call 'unsafePush' repeatedly. Is part of the class since+    -- we may be able to do this more efficiently than actually+    -- calling 'unsafePush' repeatedly.+    --+    -- N.B., this should push things in the same order as 'pushes'+    -- does.+    unsafePushes :: [Statement abt p] -> m ()+    unsafePushes = mapM_ unsafePush++    -- | Look for the statement @s@ binding the variable. If found,+    -- then call the continuation with @s@ in the context where @s@+    -- itself and everything @s@ (transitively)depends on is included+    -- but everything that (transitively)depends on @s@ is excluded;+    -- thus, the continuation may only alter the dependencies of+    -- @s@. After the continuation returns, restore all the bindings+    -- that were removed before calling the continuation. If no+    -- such @s@ can be found, then return 'Nothing' without altering+    -- the context at all.+    --+    -- N.B., the statement @s@ itself is popped! Thus, it is up to+    -- the continuation to make sure to push new statements that+    -- bind /all/ the variables bound by @s@!+    --+    -- TODO: pass the continuation more detail, so it can avoid+    -- needing to be in the 'Maybe' monad due to the redundant call+    -- to 'varEq' in the continuation. In particular, we want to+    -- do this so that we can avoid the return type @m (Maybe (Maybe r))@+    -- while still correctly handling statements like 'SStuff1'+    -- which (a) do bind variables and thus should shadow bindings+    -- further up the 'ListContext', but which (b) offer up no+    -- expression the variable is bound to, and thus cannot be+    -- altered by forcing etc. To do all this, we need to pass the+    -- 'TypeEq' proof from (the 'varEq' call in) the 'isBoundBy'+    -- call in the instance; but that means we also need some way+    -- of tying it together with the existential variable in the+    -- 'Statement'. Perhaps we should have an alternative statement+    -- type which exposes the existential?+    select+        :: Variable (a :: Hakaru)+        -> (Statement abt p -> Maybe (m r))+        -> m (Maybe r)++++-- TODO: define a new NameSupply monad in "Language.Hakaru.Syntax.Variable" for encapsulating these four fresh(en) functions?+++-- | Given some hint and type, generate a variable with a fresh+-- 'varID'.+freshVar+    :: (EvaluationMonad abt m p)+    => Text+    -> Sing (a :: Hakaru)+    -> m (Variable a)+freshVar hint typ = (\i -> Variable hint i typ) <$> freshNat+++-- TODO: move to "Language.Hakaru.Syntax.Variable" in case anyone else wants it too.+data Hint (a :: Hakaru) = Hint {-# UNPACK #-} !Text !(Sing a)++-- | Call 'freshVar' repeatedly.+-- TODO: make this more efficient than actually calling 'freshVar'+-- repeatedly.+freshVars+    :: (EvaluationMonad abt m p)+    => List1 Hint xs+    -> m (List1 Variable xs)+freshVars Nil1         = return Nil1+freshVars (Cons1 x xs) = Cons1 <$> freshVar' x <*> freshVars xs+    where+    freshVar' (Hint hint typ) = freshVar hint typ+++-- | Given a variable, return a new variable with the same hint and+-- type but with a fresh 'varID'.+freshenVar+    :: (EvaluationMonad abt m p)+    => Variable (a :: Hakaru)+    -> m (Variable a)+freshenVar x = (\i -> x{varID=i}) <$> freshNat+++-- | Call 'freshenVar' repeatedly.+-- TODO: make this more efficient than actually calling 'freshenVar'+-- repeatedly.+freshenVars+    :: (EvaluationMonad abt m p)+    => List1 Variable (xs :: [Hakaru])+    -> m (List1 Variable xs)+freshenVars Nil1         = return Nil1+freshenVars (Cons1 x xs) = Cons1 <$> freshenVar x <*> freshenVars xs+{-+-- TODO: get this faster version to typecheck! And once we do, move it to IClasses.hs or wherever 'List1'\/'DList1' end up+freshenVars = go dnil1+    where+    go  :: (EvaluationMonad abt m p)+        => DList1 Variable (ys :: [Hakaru])+        -> List1  Variable (zs :: [Hakaru])+        -> m (List1 Variable (ys ++ zs))+    go k Nil1         = return (unDList1 k Nil1) -- for typechecking, don't use 'toList1' here.+    go k (Cons1 x xs) = do+        x' <- freshenVar x+        go (k `dsnoc1` x') xs -- BUG: type error....+-}++-- | Given a size, generate a fresh Index+freshInd :: (EvaluationMonad abt m p)+         => abt '[] 'HNat+         -> m (Index (abt '[]))+freshInd s = do+  x <- freshVar T.empty SNat+  return $ Ind x s+++-- | Add a statement to the top of the context, renaming any variables+-- the statement binds and returning the substitution mapping the+-- old variables to the new ones. This is safer than 'unsafePush'+-- because it avoids variable confusion; but it is still somewhat+-- unsafe since you may forget to apply the substitution to \"the+-- rest of the term\". You almost certainly should use 'push' or+-- 'pushes' instead.+push_+    :: (ABT Term abt, EvaluationMonad abt m p)+    => Statement abt p+    -> m (Assocs (Variable :: Hakaru -> *))+push_ s = do+    (s',rho) <- freshenStatement s+    unsafePush s'+    return rho+++-- | Push a statement onto the context, renaming variables along+-- the way. The second argument represents \"the rest of the term\"+-- after we've peeled the statement off; it's passed so that we can+-- update the variable names there so that they match with the+-- (renamed)binding statement. The third argument is the continuation+-- for what to do with the renamed term. Rather than taking the+-- second and third arguments we could return an 'Assocs' giving+-- the renaming of variables; however, doing that would make it too+-- easy to accidentally drop the substitution on the floor rather+-- than applying it to the term before calling the continuation.+push+    :: (ABT Term abt, EvaluationMonad abt m p)+    => Statement abt p   -- ^ the statement to push+    -> abt xs a          -- ^ the \"rest\" of the term+    -> (abt xs a -> m r) -- ^ what to do with the renamed \"rest\"+    -> m r               -- ^ the final result+push s e k = do+    rho <- push_ s+    k (renames rho e)+++-- | Call 'push' repeatedly. (N.B., is more efficient than actually+-- calling 'push' repeatedly.) The head is pushed first and thus+-- is the furthest away in the final context, whereas the tail is+-- pushed last and is the closest in the final context.+pushes+    :: (ABT Term abt, EvaluationMonad abt m p)+    => [Statement abt p] -- ^ the statements to push+    -> abt xs a          -- ^ the \"rest\" of the term+    -> (abt xs a -> m r) -- ^ what to do with the renamed \"rest\"+    -> m r               -- ^ the final result+pushes ss e k = do+    -- TODO: is 'foldlM' the right one? or do we want 'foldrM'?+    rho <- F.foldlM (\rho s -> mappend rho <$> push_ s) mempty ss+    k (renames rho e)++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Expect.hs view
@@ -0,0 +1,385 @@+{-# LANGUAGE CPP+           , GADTs+           , EmptyCase+           , KindSignatures+           , DataKinds+           , TypeOperators+           , NoImplicitPrelude+           , ScopedTypeVariables+           , FlexibleContexts+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.05.24+-- |+-- Module      :  Language.Hakaru.Expect+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+--+----------------------------------------------------------------+module Language.Hakaru.Expect+    ( normalize+    , total+    , expect+    ) where++import           Prelude               (($), (.), error, reverse)+import qualified Data.Text             as Text+import           Data.Functor          ((<$>))+import qualified Data.Foldable         as F+import qualified Data.Traversable      as T+import qualified Data.List.NonEmpty    as NE+import           Control.Monad++import Language.Hakaru.Syntax.IClasses (Some2(..), Functor11(..))+import Language.Hakaru.Types.DataKind+import Language.Hakaru.Types.HClasses+import Language.Hakaru.Types.Sing+import Language.Hakaru.Syntax.ABT+import Language.Hakaru.Syntax.Datum+import Language.Hakaru.Syntax.DatumABT+import Language.Hakaru.Syntax.AST               hiding (Expect)+import qualified Language.Hakaru.Syntax.AST     as AST+import Language.Hakaru.Syntax.TypeOf            (typeOf)+import qualified Language.Hakaru.Syntax.Prelude as P+import Language.Hakaru.Evaluation.Types+import Language.Hakaru.Evaluation.ExpectMonad++#ifdef __TRACE_DISINTEGRATE__+import Prelude                          (show, (++))+import qualified Text.PrettyPrint       as PP+import Language.Hakaru.Pretty.Haskell   (pretty)+import Language.Hakaru.Evaluation.Types (ppStatement)+import Debug.Trace                      (trace)+#endif++----------------------------------------------------------------++-- | Convert an arbitrary measure into a probability measure; i.e.,+-- reweight things so that the total weight\/mass is 1.+normalize+    :: (ABT Term abt) => abt '[] ('HMeasure a) -> abt '[] ('HMeasure a)+normalize m = P.withWeight (P.recip $ total m) m+++-- | Compute the total weight\/mass of a measure.+total :: (ABT Term abt) => abt '[] ('HMeasure a) -> abt '[] 'HProb+total m =+    expect m . binder Text.empty (sUnMeasure $ typeOf m) $ \_ -> P.one++-- TODO: is it actually a _measurable_ function from measurable-functions+-- to probs? If so, shouldn't we also capture that in the types?+--+-- | Convert a measure into its integrator. N.B., the second argument+-- is (a representation of) a measurable function from @a@ to+-- 'HProb@. We represent it as a binding form rather than as @abt+-- '[] (a ':-> 'HProb)@ in order to avoid introducing administrative+-- redexes. We could, instead, have used a Haskell function @abt+-- '[] a -> abt '[] 'HProb@ to eliminate the administrative redexes,+-- but that would introduce other implementation difficulties we'd+-- rather avoid.+expect+    :: (ABT Term abt)+    => abt '[] ('HMeasure a)+    -> abt '[a] 'HProb+    -> abt '[] 'HProb+expect e f = runExpect (expectTerm e) f [Some2 e, Some2 f]+++residualizeExpect+    :: (ABT Term abt)+    => abt '[] ('HMeasure a)+    -> Expect abt (abt '[] a)+residualizeExpect e = do+    -- BUG: is this what we really mean? or do we actually mean the old 'emit' version?+    x <- freshVar Text.empty (sUnMeasure $ typeOf e)+    unsafePush (SStuff1 x (\c ->+        syn (AST.Expect :$ e :* bind x c :* End)) [])+    return $ var x+{-+residualizeExpect e = do+    var <$> emit Text.empty (sUnMeasure $ typeOf e)+        (\c -> syn (AST.Expect :$ e :* c :* End))+-}++-- This version checks whether the first argument is a variable or not, avoiding the extraneous let binding as appropriate. We also avoid using 'binder', which is good because it constructs the term more directly, but is bad because we make no guarantees about hygiene! We expect callers to handle that.+-- TODO: move this elsewhere, so that 'runExpect' can use it.+-- TODO: make even smarter so that we drop the let binding in case @f@ doesn't actually use it?+let_ :: (ABT Term abt) => abt '[] a -> abt '[a] b -> abt '[] b+let_ e f =+    caseVarSyn e+        (\x -> caseBind f $ \y f' -> subst y (var x) f')+        (\_ -> syn (Let_ :$ e :* f :* End))++    +expectCase+    :: (ABT Term abt)+    => abt '[] a+    -> [Branch a abt ('HMeasure b)]+    -> Expect abt (abt '[] b)+expectCase scrutinee bs = do+    -- Get the current context and then clear it.+    ctx <- Expect $ \c h -> c h (h {statements = []})+    -- Emit the old "current" context.+    Expect $ \c h -> residualizeExpectListContext (c () h) ctx+    -- @emitCaseWith@+    gms <- T.for bs $ \(Branch pat body) ->+        let (vars, body') = caseBinds body+        in  (\vars' ->+                let rho = toAssocs1 vars (fmap11 var vars')+                in  GBranch pat vars' (expectTerm $ substs rho body')+            ) <$> freshenVars vars+    Expect $ \c h ->+        syn $ Case_ scrutinee+            [ fromGBranch $ fmap (\m -> unExpect m c h) gm+            | gm <- gms+            ]++----------------------------------------------------------------+-- BUG: really rather than using 'pureEvaluate' itself, we should+-- have our own similar version which pushes the @expect _ c@ under+-- the branches; in lieu of allowing 'defaultCaseEvaluator' to+-- return a 'Neutral' term. How can we get this to work right? Seems+-- like a common problem to have since the backwards disintegrator(s)+-- have to do it too.+++-- N.B., in the ICFP 2015 pearl paper, we took the expectation of+-- bound variables prior to taking the expectation of their scope.+-- E.g., @expect(let_ v e1 e2) xs c = expect e1 xs $ \x -> expect+-- e2 (insertAssoc v x xs) c@. Whereas here, I'm being lazier and+-- performing the expectation on variable lookup. This delayed+-- evaluation preserves the expectation semantics (ICFP 2015, §5.6.0)+-- whenever (1) the variable is never used (by wasted computation),+-- or (2) used exactly once (by Tonelli's theorem); so we only need+-- to worry if (3) the variable is used more than once, in which+-- case we'll have to worry about whether the various integrals+-- commute/exchange with one another. More generally, cf. Bhat et+-- al.'s \"active variables\"++-- TODO: do we want to move this to the public API of+-- "Language.Hakaru.Evaluation.DisintegrationMonad"?+#ifdef __TRACE_DISINTEGRATE__+getStatements :: Expect abt [Statement abt 'ExpectP]+getStatements = Expect $ \c h -> c (statements h) h+#endif+++expectTerm+    :: (ABT Term abt)+    => abt '[] ('HMeasure a)+    -> Expect abt (abt '[] a)+expectTerm e = do+#ifdef __TRACE_DISINTEGRATE__+    ss <- getStatements+    trace ("\n-- expectTerm --\n"+        ++ show (pretty_Statements_withTerm ss e)+        ++ "\n") $ return ()+#endif+    w <- pureEvaluate e+    case w of+        -- TODO: if the neutral term is a 'Case_' then we want to go under it+        Neutral e'              ->+            caseVarSyn e' (residualizeExpect . var) $ \t ->+                case t of+                Case_ e1 bs -> expectCase e1 bs+                _           -> residualizeExpect e'+        Head_ (WLiteral    _)   -> error "expect: the impossible happened"+        Head_ (WCoerceTo   _ _) -> error "expect: the impossible happened"+        Head_ (WUnsafeFrom _ _) -> error "expect: the impossible happened"+        Head_ (WMeasureOp o es) -> expectMeasureOp o es+        Head_ (WDirac e1)       -> return e1+        Head_ (WMBind e1 e2)    -> do+            v1 <- expectTerm e1+            expectTerm (let_ v1 e2)+        Head_ (WPlate _ _)     -> error "TODO: expect{Plate}"+        Head_ (WChain _ _ _)   -> error "TODO: expect{Chain}"+        Head_ (WReject    _)   -> expectSuperpose []+        Head_ (WSuperpose pes) -> expectSuperpose (NE.toList pes)+++-- N.B., we guarantee that each @e@ is called with the same heap+-- @h@ and continuation @c@.+expectSuperpose+    :: (ABT Term abt)+    => [(abt '[] 'HProb, abt '[] ('HMeasure a))]+    -> Expect abt (abt '[] a)+expectSuperpose pes = do+#ifdef __TRACE_DISINTEGRATE__+    ss <- getStatements+    trace ("\n-- expectSuperpose --\n"+        ++ show (pretty_Statements_withTerm ss (syn $ Superpose_ (NE.fromList pes)))+        ++ "\n") $ return ()+#endif+    -- First, emit the current heap (so that each @p@ is emissible)+    emitExpectListContext+    -- Then emit the 'sum', and call the same continuation on each @e@+    Expect $ \c h ->+        P.sum [ p P.* unExpect (expectTerm e) c h | (p,e) <- pes]+    -- TODO: if @pes@ is null, then automatically simplify to just 0+    -- TODO: in the Lazy.tex paper, we guard against that interpretation being negative...++emitExpectListContext :: forall abt. (ABT Term abt) => Expect abt ()+emitExpectListContext = do+    ss <- Expect $ \c h -> c (statements h) (h {statements = []})+    F.traverse_ step (reverse ss) -- TODO: use composition tricks to avoid reversing @ss@+    where+    step :: Statement abt 'ExpectP -> Expect abt ()+    step s =+#ifdef __TRACE_DISINTEGRATE__+        trace ("\n-- emitExpectListContext: " ++ show (ppStatement 0 s)) $+#endif+        case s of+        SLet x body _ ->+            -- TODO: be smart about dropping unused let-bindings and inlining trivial let-bindings+            Expect $ \c h ->+                syn (Let_ :$ fromLazy body :* bind x (c () h) :* End)+        SStuff0   f _ -> Expect $ \c h -> f (c () h)+        SStuff1 _ f _ -> Expect $ \c h -> f (c () h)+++pushIntegrate+    :: (ABT Term abt)+    => abt '[] 'HReal+    -> abt '[] 'HReal+    -> Expect abt (Variable 'HReal)+pushIntegrate lo hi = do+    x <- freshVar Text.empty SReal+    unsafePush (SStuff1 x (\c ->+        syn (Integrate :$ lo :* hi :* bind x c :* End)) [])+    return x+{-+-- BUG: we assume the arguments are emissible!+emitIntegrate lo hi =+    emit Text.empty SReal (\c ->+        syn (Integrate :$ lo :* hi :* c :* End))+-}++-- Needs to be more polymorphic+pushSummate+    :: (ABT Term abt, HDiscrete_ a, SingI a)+    => abt '[] a+    -> abt '[] a+    -> Expect abt (Variable a)+pushSummate lo hi = do+    x <- freshVar Text.empty sing+    unsafePush (SStuff1 x (\c ->+        syn (Summate hDiscrete hSemiring+             :$ lo :* hi :* bind x c :* End)) [])+    return x+{-+-- BUG: we assume the arguments are emissible!+emitSummate lo hi =+    emit Text.empty SInt (\c ->+        syn (Summate :$ lo :* hi :* c :* End))+-}++-- TODO: can we / would it help to, reuse 'let_'?+-- BUG: we assume the argument is emissible!+pushLet :: (ABT Term abt) => abt '[] a -> Expect abt (Variable a)+pushLet e =+    caseVarSyn e return $ \_ -> do+        x <- freshVar Text.empty (typeOf e)+        unsafePush (SStuff1 x (\c ->+            syn (Let_ :$ e :* bind x c :* End)) [])+        return x+{-+emitLet e =+    caseVarSyn e return $ \_ ->+        emit Text.empty (typeOf e) $ \f ->+            syn (Let_ :$ e :* f :* End)+-}+++-- TODO: introduce HProb variants of integrate\/summate so we can avoid the need for 'unsafeProb' here+expectMeasureOp+    :: forall abt typs args a+    .  (ABT Term abt, typs ~ UnLCs args, args ~ LCs typs)+    => MeasureOp typs a+    -> SArgs abt args+    -> Expect abt (abt '[] a)+expectMeasureOp Lebesgue = \End ->+    var <$> pushIntegrate P.negativeInfinity P.infinity+expectMeasureOp Counting = \End ->+    var <$> pushSummate P.negativeInfinity P.infinity+expectMeasureOp Categorical = \(ps :* End) -> do+    ps' <- var <$> pushLet ps+    tot <- var <$> pushLet (P.summateV ps')+    unsafePush (SStuff0 (\c -> P.if_ (P.zero P.< tot) c P.zero) [])+    i <- freshVar Text.empty SNat+    Expect $ \c h ->+        P.summateV+            (syn (Array_ (P.size ps') (bind i ((ps' P.! var i) P.* c (var i) h))))+            P./ tot+    {-+    let_ ps $ \ps' ->+    let_ (summateV ps') $ \tot ->+    if_ (zero < tot)+        (summateV (mapWithIndex (\i p -> p * inst c i) ps') / tot)+        zero+    -}+expectMeasureOp Uniform = \(lo :* hi :* End) -> do+    -- BUG: @(let_ zero $ \y -> uniform y one)@ doesn't work as desired; *drops* the @SLet y zero@ binding entirely!!+    lo' <- var <$> pushLet lo+    hi' <- var <$> pushLet hi+    x   <- var <$> pushIntegrate lo' hi'+    unsafePush (SStuff0 (\c -> P.densityUniform lo' hi' x P.* c) [])+    return x+    {-+    let_ lo $ \lo' ->+    let_ hi $ \hi' ->+    integrate lo' hi' $ \x ->+        densityUniform lo' hi' x * inst c x+    -}+expectMeasureOp Normal = \(mu :* sd :* End) -> do+    -- HACK: for some reason w need to break apart the 'emit' and the 'emit_' or else we get a "<<loop>>" exception. Not entirely sure why, but it prolly indicates a bug somewhere.+    x <- var <$> pushIntegrate P.negativeInfinity P.infinity+    unsafePush (SStuff0 (\c -> P.densityNormal mu sd x P.* c) [])+    return x+    {-+    \c ->+        P.integrate P.negativeInfinity P.infinity $ \x ->+            P.densityNormal mu sd x P.* let_ x c)+    -}+expectMeasureOp Poisson = \(l :* End) -> do+    l' <- var <$> pushLet l+    unsafePush (SStuff0 (\c -> P.if_ (P.zero P.< l') c P.zero) [])+    x  <- var <$> pushSummate P.zero P.infinity+    unsafePush (SStuff0 (\c -> P.densityPoisson l' x P.* c) [])+    return x+    {-+    let_ l $ \l' ->+    if_ (zero < l')+        (summate zero infinity $ \x ->+            let x_ = unsafeFrom_ signed x in+            densityPoisson l' x_ * inst c x_)+        zero+    -}+expectMeasureOp Gamma = \(shape :* scale :* End) -> do+    x  <- var <$> pushIntegrate P.zero P.infinity+    x_ <- var <$> pushLet (P.unsafeProb x) -- TODO: Or is this small enough that we'd be fine using Haskell's "let" and so duplicating the coercion of a variable however often?+    unsafePush (SStuff0 (\c -> P.densityGamma shape scale x_ P.* c) [])+    return x_+    {-+    integrate zero infinity $ \x ->+        let x_ = unsafeProb x in+        densityGamma shape scale x_ * inst c x_+    -}+expectMeasureOp Beta = \(a :* b :* End) -> do+    x  <- var <$> pushIntegrate P.zero P.one+    x_ <- var <$> pushLet (P.unsafeProb x) -- TODO: Or is this small enough that we'd be fine using Haskell's "let" and so duplicating the coercion of a variable however often?+    unsafePush (SStuff0 (\c -> P.densityBeta a b x_ P.* c) [])+    return x_+    {-+    integrate zero one $ \x ->+        let x_ = unsafeProb x in+        densityBeta a b x_ * inst c x_+    -}++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Inference.hs view
@@ -0,0 +1,217 @@+{-# LANGUAGE DataKinds+           , TypeOperators+           , NoImplicitPrelude+           , FlexibleContexts+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.04.21+-- |+-- Module      :  Language.Hakaru.Inference+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- TODO: we may want to give these longer\/more-explicit names so+-- as to be a bit less ambiguous in the larger Haskell ecosystem.+----------------------------------------------------------------+module Language.Hakaru.Inference+    ( priorAsProposal+    , mh+    , mcmc+    , gibbsProposal+    , slice+    , sliceX+    , incompleteBeta+    , regBeta+    , tCDF+    , approxMh+    , kl+    ) where++import Prelude (($), (.), error, Maybe(..), return)+import Language.Hakaru.Types.DataKind+import Language.Hakaru.Types.Sing+import Language.Hakaru.Syntax.AST (Term)+import Language.Hakaru.Syntax.ABT (ABT, binder)+import Language.Hakaru.Syntax.Prelude+import Language.Hakaru.Syntax.TypeOf+import Language.Hakaru.Expect (expect, normalize)+import Language.Hakaru.Disintegrate (determine, density, disintegrate)++import qualified Data.Text as Text++----------------------------------------------------------------+----------------------------------------------------------------+priorAsProposal+    :: (ABT Term abt, SingI a, SingI b)+    => abt '[] ('HMeasure (HPair a b))+    -> abt '[] (HPair a b)+    -> abt '[] ('HMeasure (HPair a b))+priorAsProposal p x =+    bern (prob_ 0.5) >>= \c ->+    p >>= \x' ->+    dirac $+        if_ c+            (pair (fst x ) (snd x'))+            (pair (fst x') (snd x ))+++-- We don't do the accept\/reject part of MCMC here, because @min@+-- and @bern@ don't do well in @simplify@! So we'll be passing the+-- resulting AST of 'mh' to 'simplify' before plugging that into+-- @mcmc@; that's why 'easierRoadmapProg4' and 'easierRoadmapProg4''+-- have different types.+--+-- TODO: the @a@ type should be pure (aka @a ~ Expect' a@ in the old parlance).+-- BUG: get rid of the SingI requirements due to using 'lam'+mh  :: (ABT Term abt)+    => abt '[] (a ':-> 'HMeasure a)+    -> abt '[] ('HMeasure a)+    -> abt '[] (a ':-> 'HMeasure (HPair a 'HProb))+mh proposal target =+    case determine $ density target of+    Nothing -> error "mh: couldn't get density"+    Just theDensity ->+        let_ theDensity $ \mu ->+        lam' $ \old ->+            app proposal old >>= \new ->+            dirac $ pair' new (mu `app` {-pair-} new {-old-} / mu `app` {-pair-} old {-new-})+  where lam' f = lamWithVar Text.empty (sUnMeasure $ typeOf target) f+        pair'  = pair_ (sUnMeasure $ typeOf target) SProb++-- BUG: get rid of the SingI requirements due to using 'lam' in 'mh'+mcmc :: (ABT Term abt)+    => abt '[] (a ':-> 'HMeasure a)+    -> abt '[] ('HMeasure a)+    -> abt '[] (a ':-> 'HMeasure a)+mcmc proposal target =+    let_ (mh proposal target) $ \f ->+    lamWithVar Text.empty (sUnMeasure $ typeOf target) $ \old ->+        app f old >>= \new_ratio ->+        new_ratio `unpair` \new ratio ->+        bern (min (prob_ 1) ratio) >>= \accept ->+        dirac (if_ accept new old)+++gibbsProposal+    :: (ABT Term abt, SingI a, SingI b)+    => abt '[] ('HMeasure (HPair a b))+    -> abt '[] (HPair a b)+    -> abt '[] ('HMeasure (HPair a b))+gibbsProposal p xy =+    case determine $ disintegrate p of+    Nothing -> error "gibbsProposal: couldn't disintegrate"+    Just q ->+        xy `unpair` \x _y ->+        pair x <$> normalize (q `app` x)+++-- Slice sampling can be thought of:+--+-- slice target x = do+--      u  <- uniform(0, density(target, x))+--      x' <- lebesgue+--      condition (density(target, x') >= u) true+--      return x'++slice+    :: (ABT Term abt)+    => abt '[] ('HMeasure 'HReal)+    -> abt '[] ('HReal ':-> 'HMeasure 'HReal)+slice target =+    case determine $ density target of+    Nothing -> error "slice: couldn't get density"+    Just densAt ->+        lam $ \x ->+        uniform (real_ 0) (fromProb $ app densAt x) >>= \u ->+        normalize $+        lebesgue >>= \x' ->+        withGuard (u < (fromProb $ app densAt x')) $+        dirac x'+++sliceX+    :: (ABT Term abt, SingI a)+    => abt '[] ('HMeasure a)+    -> abt '[] ('HMeasure (HPair a 'HReal))+sliceX target =+    case determine $ density target of+    Nothing -> error "sliceX: couldn't get density"+    Just densAt ->+        target `bindx` \x ->+        uniform (real_ 0) (fromProb $ app densAt x)+++incompleteBeta+    :: (ABT Term abt)+    => abt '[] 'HProb+    -> abt '[] 'HProb+    -> abt '[] 'HProb+    -> abt '[] 'HProb+incompleteBeta x a b =+    let one' = real_ 1 in+    integrate (real_ 0) (fromProb x) $ \t ->+        unsafeProb t ** (fromProb a - one')+        * unsafeProb (one' - t) ** (fromProb b - one')+++regBeta -- TODO: rename 'regularBeta'+    :: (ABT Term abt)+    => abt '[] 'HProb+    -> abt '[] 'HProb+    -> abt '[] 'HProb+    -> abt '[] 'HProb+regBeta x a b = incompleteBeta x a b / betaFunc a b+++tCDF :: (ABT Term abt) => abt '[] 'HReal -> abt '[] 'HProb -> abt '[] 'HProb+tCDF x v =+    let b = regBeta (v / (unsafeProb (x*x) + v)) (v / prob_ 2) (prob_ 0.5)+    in  unsafeProb $ real_ 1 - real_ 0.5 * fromProb b+++-- BUG: get rid of the SingI requirements due to using 'lam'+approxMh+    :: (ABT Term abt, SingI a)+    => (abt '[] a -> abt '[] ('HMeasure a))+    -> abt '[] ('HMeasure a)+    -> [abt '[] a -> abt '[] ('HMeasure a)]+    -> abt '[] (a ':-> 'HMeasure a)+approxMh _ _ [] = error "TODO: approxMh for empty list"+approxMh proposal prior (_:xs) =+    case determine . density $ bindx prior proposal of+    Nothing -> error "approxMh: couldn't get density"+    Just theDensity ->+        lam $ \old ->+        let_ theDensity $ \mu ->+        unsafeProb <$> uniform (real_ 0) (real_ 1) >>= \u ->+        proposal old >>= \new ->+        let_ (u * mu `app` pair new old / mu `app` pair old new) $ \u0 ->+        let_ (l new new / l old old) $ \l0 ->+        let_ (tCDF (n - real_ 1) (udif l0 u0)) $ \delta ->+        if_ (delta < eps)+            (if_ (u0 < l0)+                (dirac new)+                (dirac old))+            (approxMh proposal prior xs `app` old)+    where+    n   = real_ 2000+    eps = prob_ 0.05+    udif lo hi = unsafeProb $ fromProb lo - fromProb hi+    l = \_d1 _d2 -> prob_ 2 -- determine (density (\theta -> x theta))++kl :: (ABT Term abt)+   => abt '[] ('HMeasure a)+   -> abt '[] ('HMeasure a)+   -> Maybe (abt '[] 'HProb)+kl p q = do+  dp <- determine $ density p+  dq <- determine $ density q+  return+    . expect p+    . binder Text.empty (sUnMeasure $ typeOf p)+    $ \i -> unsafeProb $ log (app dp i / app dq i)
+ haskell/Language/Hakaru/Observe.hs view
@@ -0,0 +1,96 @@+{-# LANGUAGE DataKinds+           , GADTs+           , FlexibleContexts+           , KindSignatures+           , PolyKinds+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.04.21+-- |+-- Module      :  Language.Hakaru.Observe+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  ppaml@indiana.edu+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- A simpler version of the work done in 'Language.Hakaru.Disintegrate'+--+-- In principle, this module's functionality is entirely subsumed+-- by the work done in Language.Hakaru.Disintegrate, so we can hope+-- to define observe in terms of disintegrate. This is still useful+-- as a guide to those that want something more in line with what other+-- probabilisitc programming systems support.+----------------------------------------------------------------+module Language.Hakaru.Observe where++import           Language.Hakaru.Syntax.AST+import           Language.Hakaru.Syntax.ABT+import           Language.Hakaru.Types.DataKind+import           Language.Hakaru.Types.Sing+import qualified Language.Hakaru.Syntax.Prelude as P+import           Language.Hakaru.Syntax.TypeOf++observe+    :: (ABT Term abt)+    => abt '[] ('HMeasure a)+    -> abt '[] a +    -> abt '[] ('HMeasure a)+observe m a = observeAST (LC_ m) (LC_ a)+++-- TODO: move this to ABT.hs+freshenVarRe+    :: ABT syn abt => Variable (a :: k) -> abt '[] (b :: k) -> Variable a+freshenVarRe x m = x {varID = nextFree m `max` nextBind m}+++observeAST+    :: (ABT Term abt)+    => LC_ abt ('HMeasure a)+    -> LC_ abt a+    -> abt '[] ('HMeasure a)+observeAST (LC_ m) (LC_ a) =+    caseVarSyn m observeVar $ \ast ->+        case ast of+        -- TODO: Add a name supply+        Let_ :$ e1 :* e2 :* End ->+            caseBind e2 $ \x e2' ->+            let x'   = freshenVarRe x m+                e2'' = rename x x' e2'+            in syn (Let_ :$ e1 :* bind x' (observe e2'' a) :* End)+        --Dirac :$ e :* End -> P.if_ (e P.== a) (P.dirac a) P.reject+        -- TODO: Add a name supply+        MBind :$ e1 :* e2 :* End ->+            caseBind e2 $ \x e2' ->+            let x'   = freshenVarRe x m+                e2'' = rename x x' e2'+            in syn (MBind :$ e1 :* bind x' (observe e2'' a) :* End)+        Plate :$ e1 :* e2 :* End ->+            caseBind e2 $ \x e2' ->+            let a' = syn (ArrayOp_ (Index (sUnMeasure $ typeOf e2'))+                        :$ a+                        :* var x :* End)+            in syn (Plate :$ e1 :* bind x (observe e2' a') :* End)+        MeasureOp_ op :$ es -> observeMeasureOp op es a+        _ -> error "observe can only be applied to measure primitives"++-- This function can't inspect a variable due to+-- calls to subst that happens in Let_ and Bind_+observeVar = error "observe can only be applied measure primitives"++observeMeasureOp+    :: (ABT Term abt, typs ~ UnLCs args, args ~ LCs typs)+    => MeasureOp typs a+    -> SArgs abt args+    -> abt '[] a+    -> abt '[] ('HMeasure a)+observeMeasureOp Normal = \(mu :* sd :* End) a ->+    P.withWeight (P.densityNormal mu sd a) (P.dirac a)+observeMeasureOp Uniform = \(lo :* hi :* End) a ->+    P.if_ (lo P.<= a P.&& a P.<= hi)+        (P.withWeight (P.unsafeProb $ P.recip $ hi P.- lo) (P.dirac a))+        (P.reject (SMeasure SReal))+observeMeasureOp _ = error "TODO{Observe:observeMeasureOp}"
+ haskell/Language/Hakaru/Parser/AST.hs view
@@ -0,0 +1,448 @@+{-# LANGUAGE CPP+           , GADTs+           , DataKinds+           , PolyKinds+           , ExistentialQuantification+           , StandaloneDeriving+           , TypeFamilies+           , OverloadedStrings+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}++module Language.Hakaru.Parser.AST where++import           Prelude       hiding (replicate, unlines)+import           Control.Arrow ((***))++import qualified Data.Foldable       as F+import qualified Data.Vector         as V+import qualified Data.Number.Nat     as N+import qualified Data.Number.Natural as N+import qualified Data.List.NonEmpty  as L++import Language.Hakaru.Types.DataKind+import Language.Hakaru.Types.Sing+import Language.Hakaru.Types.Coercion+import Language.Hakaru.Syntax.ABT    hiding (Var, Bind)+import Language.Hakaru.Syntax.AST+    (Literal(..), MeasureOp(..), LCs(), UnLCs ())+import Language.Hakaru.Syntax.IClasses++#if __GLASGOW_HASKELL__ < 710+import Data.Monoid   (Monoid(..))+#endif++import Data.Text+import Text.Printf+import Text.Parsec (SourcePos)+import Text.Parsec.Pos++-- N.B., because we're not using the ABT's trick for implementing a HOAS API, we can make the identifier strict.+data Name = Name {-# UNPACK #-}!N.Nat {-# UNPACK #-}!Text+    deriving (Read, Show, Eq, Ord)++nameID :: Name -> N.Nat+nameID (Name i _) = i++hintID :: Name -> Text+hintID (Name _ t) = t++----------------------------------------------------------------+----------------------------------------------------------------++type Name' = Text++data Branch' a+    = Branch'  (Pattern' Name') (AST' a)+    | Branch'' (Pattern' Name)  (AST' a)+    deriving (Eq, Show)++data Pattern' a+    = PVar'  a+    | PWild'+    | PData' (PDatum a)+    deriving (Eq, Show)++data PDatum a = DV Name' [Pattern' a]+    deriving (Eq, Show)++-- Meta stores start and end position for AST in source code+data SourceSpan = SourceSpan !SourcePos !SourcePos+    deriving (Eq, Show)++numberLine :: Text -> Int -> Text+numberLine s n = append (pack (printf "%5d| " n)) s++printSourceSpan :: SourceSpan -> V.Vector Text -> Text+printSourceSpan (SourceSpan start stop) input+    | sourceLine start == sourceLine stop =+        unlines [ numberLine endLine (sourceLine stop)+                , append "       " textSpan+                ]+    | otherwise                           =+        unlines $ flip fmap [sourceLine start .. sourceLine stop] $ \i ->+            numberLine (input V.! (i - 1)) i+   where endLine  = input V.! (sourceLine stop - 1)+         spanLen  = sourceColumn stop - sourceColumn start+         textSpan =+             append (replicate (sourceColumn start - 1) " ")+                    (replicate spanLen "^")++data Literal'+    = Nat  Integer+    | Int  Integer+    | Prob Rational+    | Real Rational+    deriving (Eq, Show)++data NaryOp+    = And | Or   | Xor+    | Iff | Min  | Max +    | Sum | Prod+    deriving (Eq, Show)++data ArrayOp = Index_ | Size | Reduce++data TypeAST'+    = TypeVar Name'+    | TypeApp Name'    [TypeAST']+    | TypeFun TypeAST' TypeAST'+    deriving (Eq, Show)++data AST' a+    = Var a+    | Lam a TypeAST' (AST' a) +    | App (AST' a) (AST' a)+    | Let a    (AST' a) (AST' a)+    | If  (AST' a) (AST' a) (AST' a)+    | Ann (AST' a) TypeAST'+    | Infinity'+    | ULiteral Literal'+    | NaryOp NaryOp [AST' a]+    | Unit+    | Empty+    | Pair (AST' a) (AST' a)+    | Array a (AST' a) (AST' a)+    | Index (AST' a) (AST' a)+    | Case  (AST' a) [(Branch' a)] -- match+    | Dirac (AST' a)+    | Bind  a  (AST' a) (AST' a)+    | Plate a  (AST' a) (AST' a)+    | Chain a  (AST' a) (AST' a) (AST' a)+    | Integrate a (AST' a) (AST' a) (AST' a)+    | Summate   a (AST' a) (AST' a) (AST' a)+    | Product   a (AST' a) (AST' a) (AST' a)+    | Expect a (AST' a) (AST' a)+    | Observe  (AST' a) (AST' a)+    | Msum  [AST' a]+    | Data  a [TypeAST']+    | WithMeta (AST' a) SourceSpan+    deriving (Show)++instance Eq a => Eq (AST' a) where+    (Var t)             == (Var t')                 = t    == t'+    (Lam n  e1 e2)      == (Lam n' e1' e2')         = n    == n'  &&+                                                      e1   == e1' &&+                                                      e2   == e2'+    (App    e1 e2)      == (App    e1' e2')         = e1   == e1' &&+                                                      e2   == e2'+    (Let n  e1 e2)      == (Let n' e1' e2')         = n    == n'  &&+                                                      e1   == e1' &&+                                                      e2   == e2'+    (If  c  e1 e2)      == (If  c' e1' e2')         = c    == c'  &&+                                                      e1   == e1' &&+                                                      e2   == e2'+    (Ann e typ)         == (Ann e' typ')            = e    == e'  &&+                                                      typ  == typ'+    Infinity'           == Infinity'                = True+    (ULiteral v)        == (ULiteral v')            = v    == v'+    (NaryOp op args)    == (NaryOp op' args')       = op   == op' &&+                                                      args == args'+    Unit                == Unit                     = True+    Empty               == Empty                    = True+    (Pair  e1 e2)       == (Pair   e1' e2')         = e1   == e1' &&+                                                      e2   == e2'+    (Array e1 e2 e3)    == (Array  e1' e2' e3')     = e1   == e1' &&+                                                      e2   == e2' &&+                                                      e3   == e3'+    (Index e1 e2)       == (Index  e1' e2')         = e1   == e1' &&+                                                      e2   == e2'+    (Case  e1 bs)       == (Case   e1' bs')         = e1   == e1' &&+                                                      bs   == bs'+    (Dirac e1)          == (Dirac  e1')             = e1   == e1'+    (Bind  e1 e2 e3)    == (Bind   e1' e2' e3')     = e1   == e1' &&+                                                      e2   == e2' &&+                                                      e3   == e3'+    (Plate e1 e2 e3)    == (Plate  e1' e2' e3')     = e1   == e1' &&+                                                      e2   == e2' &&+                                                      e3   == e3'+    (Chain e1 e2 e3 e4) == (Chain  e1' e2' e3' e4') = e1   == e1' &&+                                                      e2   == e2' &&+                                                      e3   == e3' &&+                                                      e4   == e4'+    (Integrate a b c d) == (Integrate  a' b' c' d') = a    == a' &&+                                                      b    == b' &&+                                                      c    == c' &&+                                                      d    == d'+    (Summate   a b c d) == (Summate    a' b' c' d') = a    == a' &&+                                                      b    == b' &&+                                                      c    == c' &&+                                                      d    == d'+    (Product   a b c d) == (Product    a' b' c' d') = a    == a' &&+                                                      b    == b' &&+                                                      c    == c' &&+                                                      d    == d'+    (Expect e1 e2 e3)   == (Expect e1' e2' e3')     = e1   == e1' &&+                                                      e2   == e2' &&+                                                      e3   == e3'+    (Observe  e1 e2)    == (Observe    e1' e2')     = e1   == e1' &&+                                                      e2   == e2'+    (Msum  es)          == (Msum   es')             = es   == es'+    (Data  e1 ts)       == (Data   e1' ts')         = e1   == e1' &&+                                                      ts   == ts'+    (WithMeta e1 _ )    == e2                       = e1   == e2+    e1                  == (WithMeta e2 _)          = e1   == e2+    _                   == _                        = False+                                 +data Import a = Import a+     deriving (Eq, Show)+data ASTWithImport' a = ASTWithImport' [Import a] (AST' a)+     deriving (Eq, Show)++----------------------------------------------------------------+----------------------------------------------------------------++val :: Literal' -> Some1 Literal+val (Nat  n) = Some1 $ LNat  (N.unsafeNatural n)+val (Int  n) = Some1 $ LInt  n+val (Prob n) = Some1 $ LProb (N.unsafeNonNegativeRational n)+val (Real n) = Some1 $ LReal n++data PrimOp+    = Not | Impl | Diff   | Nand | Nor+    | Pi+    | Sin        | Cos    | Tan+    | Asin       | Acos   | Atan+    | Sinh       | Cosh   | Tanh+    | Asinh      | Acosh  | Atanh+    | RealPow    | NatPow+    | Exp        | Log    | Infinity+    | GammaFunc  | BetaFunc+    | Equal      | Less+    | Negate     | Recip+    | Abs        | Signum | NatRoot | Erf+    deriving (Eq, Show)++data SomeOp op where+    SomeOp+        :: (typs ~ UnLCs args, args ~ LCs typs)+        => !(op typs a)+        -> SomeOp op++data SSing =+    forall (a :: Hakaru). SSing !(Sing a)++data Branch_ abt = Branch_ Pattern (abt '[] 'U)++fmapBranch+    :: (f '[] 'U -> g '[] 'U)+    -> Branch_ f+    -> Branch_ g+fmapBranch f (Branch_ pat e) = Branch_ pat (f e)++foldBranch+    :: (abt '[] 'U -> m)+    -> Branch_ abt+    -> m+foldBranch f (Branch_ _ e) = f e++data Pattern+    = PWild+    | PVar Name+    | PDatum Text PCode++data PFun+    = PKonst Pattern+    | PIdent Pattern++data PStruct+    = PEt PFun PStruct+    | PDone++data PCode+    = PInr PCode+    | PInl PStruct++infixr 7 `Et`, `PEt`++data DFun abt+    = Konst (abt '[] 'U)+    | Ident (abt '[] 'U)++data DStruct abt+    = Et (DFun abt) (DStruct abt)+    | Done++data DCode abt+    = Inr (DCode   abt)+    | Inl (DStruct abt)++data Datum abt = Datum Text (DCode abt)++fmapDatum+    :: (f '[] 'U -> g '[] 'U)+    -> Datum f+    -> Datum g+fmapDatum f (Datum t dcode) = Datum t (fdcode f dcode)+   where fdcode   f' (Inr d)    = Inr (fdcode   f' d)+         fdcode   f' (Inl d)    = Inl (fdstruct f' d)+         fdstruct f' (Et df ds) = Et  (fdfun    f' df)+                                      (fdstruct f' ds)+         fdstruct _  Done       = Done+         fdfun    f' (Konst e)  = Konst (f' e)+         fdfun    f' (Ident e)  = Ident (f' e)++foldDatum+    :: (Monoid m)+    => (abt '[] 'U -> m)+    -> Datum abt+    -> m+foldDatum f (Datum _ dcode) = fdcode f dcode+   where fdcode   f' (Inr d)    = fdcode   f' d+         fdcode   f' (Inl d)    = fdstruct f' d+         fdstruct f' (Et df ds) = fdfun    f' df `mappend`+                                  fdstruct f' ds+         fdstruct _  Done       = mempty+         fdfun    f' (Konst e)  = f' e+         fdfun    f' (Ident e)  = f' e+++-- | The kind containing exactly one type.+data Untyped = U+    deriving (Read, Show)++data instance Sing (a :: Untyped) where+    SU :: Sing 'U++instance SingI 'U where+    sing = SU++instance Show (Sing (a :: Untyped)) where+    showsPrec = showsPrec1+    show      = show1++instance Show1 (Sing :: Untyped -> *) where+    showsPrec1 _ SU = ("SU" ++)++instance Eq (Sing (a :: Untyped)) where+    SU == SU = True++instance Eq1 (Sing :: Untyped -> *) where+    eq1 SU SU = True++instance JmEq1 (Sing :: Untyped -> *) where+    jmEq1 SU SU = Just Refl++nameToVar :: Name -> Variable 'U+nameToVar (Name i h) = Variable h i SU++data Term :: ([Untyped] -> Untyped -> *) -> Untyped -> * where+    Lam_       :: SSing            -> abt '[ 'U ] 'U  -> Term abt 'U+    App_       :: abt '[] 'U       -> abt '[]     'U  -> Term abt 'U+    Let_       :: abt '[] 'U       -> abt '[ 'U ] 'U  -> Term abt 'U+    Ann_       :: SSing            -> abt '[]     'U  -> Term abt 'U+    CoerceTo_  :: Some2 Coercion   -> abt '[]     'U  -> Term abt 'U+    UnsafeTo_  :: Some2 Coercion   -> abt '[]     'U  -> Term abt 'U+    PrimOp_    :: PrimOp           -> [abt '[] 'U]    -> Term abt 'U+    ArrayOp_   :: ArrayOp          -> [abt '[] 'U]    -> Term abt 'U+    MeasureOp_ :: SomeOp MeasureOp -> [abt '[] 'U]    -> Term abt 'U+    NaryOp_    :: NaryOp           -> [abt '[] 'U]    -> Term abt 'U+    Literal_   :: Some1 Literal                       -> Term abt 'U+    Empty_     ::                                        Term abt 'U+    Pair_      :: abt '[] 'U       -> abt '[]     'U  -> Term abt 'U+    Array_     :: abt '[] 'U       -> abt '[ 'U ] 'U  -> Term abt 'U+    Datum_     :: Datum abt                           -> Term abt 'U+    Case_      :: abt '[] 'U       -> [Branch_ abt]   -> Term abt 'U+    Dirac_     :: abt '[] 'U                          -> Term abt 'U+    MBind_     :: abt '[] 'U       -> abt '[ 'U ] 'U  -> Term abt 'U+    Plate_     :: abt '[] 'U       -> abt '[ 'U ] 'U  -> Term abt 'U+    Chain_     :: abt '[] 'U       -> abt '[]     'U  -> abt '[ 'U ] 'U -> Term abt 'U+    Integrate_ :: abt '[] 'U       -> abt '[]     'U  -> abt '[ 'U ] 'U -> Term abt 'U+    Summate_   :: abt '[] 'U       -> abt '[]     'U  -> abt '[ 'U ] 'U -> Term abt 'U+    Product_   :: abt '[] 'U       -> abt '[]     'U  -> abt '[ 'U ] 'U -> Term abt 'U+    Expect_    :: abt '[] 'U       -> abt '[ 'U ] 'U  -> Term abt 'U+    Observe_   :: abt '[] 'U       -> abt '[]     'U  -> Term abt 'U+    Superpose_ :: L.NonEmpty (abt '[] 'U, abt '[] 'U) -> Term abt 'U+    Reject_    ::                                        Term abt 'U+++-- TODO: instance of Traversable21 for Term+instance Functor21 Term where+    fmap21 f (Lam_       typ e1)    = Lam_       typ    (f e1)+    fmap21 f (App_       e1  e2)    = App_       (f e1) (f e2)+    fmap21 f (Let_       e1  e2)    = Let_       (f e1) (f e2)+    fmap21 f (Ann_       typ e1)    = Ann_       typ    (f e1)+    fmap21 f (CoerceTo_  c   e1)    = CoerceTo_  c      (f e1)+    fmap21 f (UnsafeTo_  c   e1)    = UnsafeTo_  c      (f e1)+    fmap21 f (PrimOp_    op  es)    = PrimOp_    op     (fmap f es)+    fmap21 f (ArrayOp_   op  es)    = ArrayOp_   op     (fmap f es)+    fmap21 f (MeasureOp_ op  es)    = MeasureOp_ op     (fmap f es)+    fmap21 f (NaryOp_    op  es)    = NaryOp_    op     (fmap f es)+    fmap21 _ (Literal_   v)         = Literal_   v+    fmap21 _ Empty_                 = Empty_+    fmap21 f (Pair_      e1  e2)    = Pair_      (f e1) (f e2)+    fmap21 f (Array_     e1  e2)    = Array_     (f e1) (f e2)+    fmap21 f (Datum_     d)         = Datum_     (fmapDatum f d)+    fmap21 f (Case_      e1  bs)    = Case_      (f e1) (fmap (fmapBranch f) bs)+    fmap21 f (Dirac_     e1)        = Dirac_     (f e1)+    fmap21 f (MBind_     e1  e2)    = MBind_     (f e1) (f e2)+    fmap21 f (Plate_     e1  e2)    = Plate_     (f e1) (f e2)+    fmap21 f (Chain_     e1  e2 e3) = Chain_     (f e1) (f e2) (f e3)+    fmap21 f (Integrate_ e1  e2 e3) = Integrate_ (f e1) (f e2) (f e3)+    fmap21 f (Summate_   e1  e2 e3) = Summate_   (f e1) (f e2) (f e3)+    fmap21 f (Product_   e1  e2 e3) = Product_   (f e1) (f e2) (f e3)+    fmap21 f (Expect_    e1  e2)    = Expect_    (f e1) (f e2)+    fmap21 f (Observe_   e1  e2)    = Observe_   (f e1) (f e2)+    fmap21 f (Superpose_ es)        = Superpose_ (L.map (f *** f) es)+    fmap21 _ Reject_                = Reject_++instance Foldable21 Term where+    foldMap21 f (Lam_       _  e1)    = f e1+    foldMap21 f (App_       e1 e2)    = f e1 `mappend` f e2+    foldMap21 f (Let_       e1 e2)    = f e1 `mappend` f e2+    foldMap21 f (Ann_       _  e1)    = f e1+    foldMap21 f (CoerceTo_  _  e1)    = f e1+    foldMap21 f (UnsafeTo_  _  e1)    = f e1+    foldMap21 f (PrimOp_    _  es)    = F.foldMap f es+    foldMap21 f (ArrayOp_   _  es)    = F.foldMap f es+    foldMap21 f (MeasureOp_ _  es)    = F.foldMap f es+    foldMap21 f (NaryOp_    _  es)    = F.foldMap f es+    foldMap21 _ (Literal_   _)        = mempty+    foldMap21 _ Empty_                = mempty+    foldMap21 f (Pair_      e1 e2)    = f e1 `mappend` f e2+    foldMap21 f (Array_     e1 e2)    = f e1 `mappend` f e2+    foldMap21 f (Datum_     d)        = foldDatum f d+    foldMap21 f (Case_      e1 bs)    = f e1 `mappend` F.foldMap (foldBranch f) bs+    foldMap21 f (Dirac_     e1)       = f e1+    foldMap21 f (MBind_     e1 e2)    = f e1 `mappend` f e2+    foldMap21 f (Plate_     e1 e2)    = f e1 `mappend` f e2+    foldMap21 f (Chain_     e1 e2 e3) = f e1 `mappend` f e2 `mappend` f e3+    foldMap21 f (Integrate_ e1 e2 e3) = f e1 `mappend` f e2 `mappend` f e3+    foldMap21 f (Summate_   e1 e2 e3) = f e1 `mappend` f e2 `mappend` f e3+    foldMap21 f (Product_   e1 e2 e3) = f e1 `mappend` f e2 `mappend` f e3+    foldMap21 f (Expect_    e1 e2)    = f e1 `mappend` f e2+    foldMap21 f (Observe_   e1 e2)    = f e1 `mappend` f e2+    foldMap21 f (Superpose_ es)       = F.foldMap (\(e1,e2) -> f e1 `mappend` f e2) es+    foldMap21 _ Reject_               = mempty++type AST      = MetaABT SourceSpan Term '[] 'U+type MetaTerm = Term (MetaABT SourceSpan Term) 'U+type Branch   = Branch_ (MetaABT SourceSpan Term)++type DFun_    = DFun    (MetaABT SourceSpan Term)+type DStruct_ = DStruct (MetaABT SourceSpan Term)+type DCode_   = DCode   (MetaABT SourceSpan Term)++----------------------------------------------------------------+---------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Parser/Maple.hs view
@@ -0,0 +1,598 @@+{-# LANGUAGE CPP, OverloadedStrings, LambdaCase #-}+{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+module Language.Hakaru.Parser.Maple where++import           Prelude             hiding (not, and, sum, product)+import           Control.Monad.Identity+import           Data.Text           (Text)+import qualified Data.Text           as Text+import           Data.Ratio+#if __GLASGOW_HASKELL__ < 710+import           Data.Functor        ((<$>))+import           Control.Applicative (Applicative(..))+#endif+import           Text.Parsec+import           Text.Parsec.Text+import qualified Text.Parsec.Token   as Token+import           Text.Parsec.Language++import           Language.Hakaru.Parser.AST hiding (Less, Equal)++----------------------------------------------------------------++style :: GenLanguageDef Text st Identity+style = Token.LanguageDef+    { Token.commentStart   = "(*"+    , Token.commentEnd     = "*)"+    , Token.commentLine    = "#"+    , Token.nestedComments = True+    , Token.identStart     = letter <|> char '_'+    , Token.identLetter    = alphaNum <|> oneOf "_"+    , Token.opStart        = Token.opLetter style+    , Token.opLetter       = oneOf "+-*/<>="+    , Token.reservedOpNames= []+    , Token.reservedNames  = []+    , Token.caseSensitive  = False+    }++type TokenParser a = Token.GenTokenParser Text a Identity++lexer :: TokenParser ()+lexer = Token.makeTokenParser style++integer :: Parser Integer+integer = Token.integer lexer++parens :: Parser a -> Parser a+parens = Token.parens lexer++identifier :: Parser Text+identifier = Text.pack <$> Token.identifier lexer++stringLiteral :: Parser Text+stringLiteral = Text.pack <$> Token.stringLiteral lexer++comma :: Parser String+comma = Token.comma lexer++commaSep :: Parser a -> Parser [a]+commaSep = Token.commaSep lexer++symTable :: [(Text, Text)]+symTable =+    [ ("Gaussian",    "normal")+    , ("BetaD",       "beta")+    , ("GammaD",      "gamma")+    , ("PoissonD",    "poisson")+    , ("Weight",      "weight")+    , ("Lebesgue",    "lebesgue")+    , ("Counting",    "counting")+    , ("Uniform",     "uniform")+    , ("Ret",         "dirac")+    , ("Categorical", "categorical")+    , ("Geometric",   "geometric")+    , ("Not",         "not")+    , ("Pi",          "pi")+    , ("ln",          "log")+    , ("Beta",        "betaFunc")+    , ("GAMMA",       "gammaFunc")+    , ("csgn",        "signum")+    -- Type symbols+    , ("Real",        "real")+    , ("Prob",        "prob")+    , ("Measure",     "measure")+    , ("Bool",        "bool")+    ]++rename :: Text -> Text+rename x =+    case lookup x symTable of+    Just x' -> x'+    Nothing -> x++arg :: Parser a -> Parser [a]+arg e = parens (commaSep e)++text :: Text -> Parser Text+text = liftM Text.pack <$> string <$> Text.unpack++----------------------------------------------------------------+-- | Grammar of Inert Expressions++data NumOp = Pos | Neg+    deriving (Eq, Show)++data ArgOp+    = Float | Power  | Rational+    | Func  | ExpSeq | Sum_+    | Prod_ | Less   | Equal+    | NotEq | Not_   | And_+    | Range | List+    deriving (Eq, Show)++data InertExpr+    = InertName Text+    | InertNum  NumOp Integer+    | InertArgs ArgOp [InertExpr]+    deriving (Eq, Show)++----------------------------------------------------------------+-- Parsing String into Inert Expression++func :: Parser InertExpr+func =+    InertArgs+    <$> (text "_Inert_FUNCTION" *> return Func)+    <*> arg expr++name :: Parser InertExpr+name =+    InertName+    <$> (text "_Inert_NAME" *> parens stringLiteral)++assignedname :: Parser InertExpr+assignedname =+    InertName+    <$> (text "_Inert_ASSIGNEDNAME"+        *> parens+            (  stringLiteral+            <* comma+            <* stringLiteral))++assignedlocalname :: Parser InertExpr+assignedlocalname =+    InertName+    <$> (text "_Inert_ASSIGNEDLOCALNAME"+        *> parens+            (  stringLiteral+            <* comma+            <* stringLiteral+            <* comma+            <* integer))++expseq :: Parser InertExpr+expseq =+    InertArgs+    <$> (text "_Inert_EXPSEQ" *> return ExpSeq)+    <*> arg expr++intpos :: Parser InertExpr+intpos =+    InertNum+    <$> (text "_Inert_INTPOS" *> return Pos)+    <*> parens integer++intneg :: Parser InertExpr+intneg =+    InertNum+    <$> (text "_Inert_INTNEG" *> return Neg)+    <*> fmap negate (parens integer)++float :: Parser InertExpr+float  =+    InertArgs+    <$> (text "_Inert_FLOAT" *> return Float)+    <*> arg expr++power :: Parser InertExpr+power =+    InertArgs+    <$> (text "_Inert_POWER" *> return Power)+    <*> arg expr++range :: Parser InertExpr+range =+    InertArgs+    <$> (text "_Inert_RANGE" *> return Range)+    <*> arg expr++and :: Parser InertExpr+and =+    InertArgs+    <$> (text "_Inert_AND" *> return And_)+    <*> arg expr++list :: Parser InertExpr+list =+    InertArgs+    <$> (text "_Inert_LIST" *> return List)+    <*> arg expr++sum :: Parser InertExpr+sum =+    InertArgs+    <$> (text "_Inert_SUM" *> return Sum_)+    <*> arg expr++product :: Parser InertExpr+product =+    InertArgs+    <$> (text "_Inert_PROD" *> return Prod_)+    <*> arg expr++rational :: Parser InertExpr+rational =+    InertArgs+    <$> (text "_Inert_RATIONAL" *> return Rational)+    <*> arg expr++lessthan :: Parser InertExpr+lessthan =+    InertArgs+    <$> (text "_Inert_LESSTHAN" *> return Less)+    <*> arg expr++not :: Parser InertExpr+not =+    InertArgs+    <$> (text "_Inert_NOT" *> return Not_)+    <*> arg expr++lesseq :: Parser InertExpr+lesseq = do+    text "_Inert_LESSEQ"+    args <- arg expr+    return $ InertArgs Not_+               [ InertArgs Less (reverse args)]++equal :: Parser InertExpr+equal =+    InertArgs+    <$> (text "_Inert_EQUATION" *> return Equal)+    <*> arg expr++noteq :: Parser InertExpr+noteq =+    InertArgs+    <$> (text "_Inert_INEQUAT" *> return NotEq)+    <*> arg expr++expr :: Parser InertExpr+expr =  try func+    <|> try name+    <|> try list+    <|> try and+    <|> try not+    <|> try lessthan+    <|> try lesseq+    <|> try equal+    <|> try noteq+    <|> try assignedname+    <|> try assignedlocalname+    <|> try expseq+    <|> try intpos+    <|> try intneg+    <|> try range+    <|> try power+    <|> try sum+    <|> try product+    <|> try rational+    <|> float++parseMaple :: Text -> Either ParseError InertExpr+parseMaple txt =+    runParser (expr <* eof) () (Text.unpack txt) (Text.filter (/= '\n') txt)++----------------------------------------------------------------+-- Parsing InertExpr to AST' Text++collapseNaryOp :: NaryOp -> [AST' Text] -> [AST' Text]+collapseNaryOp op =+    concatMap (\case+                NaryOp op' e | op == op' ->  e+                t                        -> [t])+++maple2AST :: InertExpr -> AST' Text+maple2AST (InertNum Pos i)       = ULiteral $ Nat $ fromInteger i+maple2AST (InertNum Neg i)       = ULiteral $ Int $ fromInteger i+maple2AST (InertName "infinity") = Infinity'+maple2AST (InertName t)          = Var (rename t)++maple2AST (InertArgs Float [InertNum Pos a, InertNum _ b]) = +    ULiteral . Prob $ fromInteger a * (10 ^ b)++maple2AST (InertArgs Float [InertNum Neg a, InertNum _ b]) = +    ULiteral . Real $ fromInteger a * (10 ^ b)++maple2AST (InertArgs Func+        [InertName "Bind", InertArgs ExpSeq [e1, InertName x, e2]]) =+    Bind x (maple2AST e1) (maple2AST e2)++maple2AST (InertArgs Func+        [InertName "Datum", InertArgs ExpSeq [InertName h, d]]) =+    mapleDatum2AST h d++maple2AST (InertArgs Func [InertName "Lebesgue", _]) =+    Var "lebesgue"++maple2AST (InertArgs Func [InertName "Counting", _]) =+    Var "counting"++maple2AST (InertArgs Func+        [InertName "lam", InertArgs ExpSeq [InertName x, typ, e1]]) =+    Lam x (maple2Type typ) (maple2AST e1)++maple2AST (InertArgs Func+        [InertName "app", InertArgs ExpSeq [e1, e2]]) =+    App (maple2AST e1) (maple2AST e2)++maple2AST (InertArgs Func+        [InertName "NegativeBinomial", InertArgs ExpSeq [e1, e2]]) =+    Bind "i" (op2 "gamma" r (recip_ $ recip_ p -. (lit $ Prob 1)))+         (App (Var "poisson") (Var "i"))+    where recip_     = App (Var "recip")+          x -. y     = NaryOp Sum [x, App (Var "negate") y]+          op2  s x y = App (App (Var s) x) y+          lit        = ULiteral+          r          = maple2AST e1+          p          = maple2AST e2++maple2AST (InertArgs Func+        [InertName "Msum", InertArgs ExpSeq []]) =+    Var "reject"++maple2AST (InertArgs Func+        [InertName "Msum", InertArgs ExpSeq es]) =+    Msum (map maple2AST es)++maple2AST (InertArgs Func+        [InertName "ary", InertArgs ExpSeq [e1, InertName x, e2]]) =+    Array x (maple2AST e1) (maple2AST e2)++maple2AST (InertArgs Func+        [InertName "idx", InertArgs ExpSeq [e1, e2]]) =+    Index (maple2AST e1) (maple2AST e2)++maple2AST (InertArgs Func+        [InertName "piecewise", InertArgs ExpSeq es]) = go es where+  go [e1,e2]      = If (maple2AST e1) (maple2AST e2) (ULiteral (Nat 0))+  go [e1,e2,e3]   = If (maple2AST e1) (maple2AST e2) (maple2AST e3)+  go [e1,e2,_,e3] = If (maple2AST e1) (maple2AST e2) (maple2AST e3)+  go (e1:e2:rest) = If (maple2AST e1) (maple2AST e2) (go rest)++maple2AST (InertArgs Func+        [InertName "max", InertArgs ExpSeq es]) =+    NaryOp Max (map maple2AST es)++maple2AST (InertArgs Func+        [InertName "min", InertArgs ExpSeq es]) =+    NaryOp Min (map maple2AST es)++maple2AST (InertArgs Func+        [InertName "Ei", InertArgs ExpSeq [e1, e2]]) =+    Integrate "t" (maple2AST e2) Infinity'+    (NaryOp Prod [ App (Var "exp")   (App (Var "negate") (Var "t"))+                 , App (Var "recip")+                       (App (App (Var "^") (Var "t")) (maple2AST e1))+                 ])++maple2AST (InertArgs Func+        [ InertName "case"+        , InertArgs ExpSeq+            [e1, InertArgs Func+                [ InertName "Branches"+                , InertArgs ExpSeq bs]]]) =+    Case (maple2AST e1) (map branch bs)++maple2AST (InertArgs Func+        [InertName "Plate", InertArgs ExpSeq [e1, InertName x, e2]]) =+    Plate x (maple2AST e1) (maple2AST e2)++maple2AST (InertArgs Func+        [InertName "And", InertArgs ExpSeq es]) =+    NaryOp And (map maple2AST es)++maple2AST (InertArgs Func+        [ InertName "int"+        , InertArgs ExpSeq+           [ f+           , InertArgs Equal+             [ InertName x+             , InertArgs Range [lo, hi]]]]) =+    Integrate x (maple2AST lo) (maple2AST hi) (maple2AST f)++maple2AST (InertArgs Func+        [ InertName "Int"+        , InertArgs ExpSeq+           [ f+           , InertArgs Equal+             [ InertName x+             , InertArgs Range [lo, hi]]]]) =+    Integrate x (maple2AST lo) (maple2AST hi) (maple2AST f)++maple2AST (InertArgs Func+        [ InertName "SumIE"+        , InertArgs ExpSeq+           [ f+           , InertArgs Equal+             [ InertName x+             , InertArgs Range [lo, hi]]]]) =+    Summate x (maple2AST lo) (maple2AST hi) (maple2AST f)++maple2AST (InertArgs Func+        [ InertName "ProductIE"+        , InertArgs ExpSeq+           [ f+           , InertArgs Equal+             [ InertName x+             , InertArgs Range [lo, hi]]]]) =+    Product x (maple2AST lo) (maple2AST hi) (maple2AST f)++maple2AST (InertArgs Func+        [f, InertArgs ExpSeq es]) =+    foldl App (maple2AST f) (map maple2AST es)++maple2AST (InertArgs And_  es) = NaryOp And  (collapseNaryOp And  (map maple2AST es))+maple2AST (InertArgs Sum_  es) = NaryOp Sum  (collapseNaryOp Sum  (map maple2AST es))+maple2AST (InertArgs Prod_ es) = NaryOp Prod (collapseNaryOp Prod (map maple2AST es))++maple2AST (InertArgs Not_ [e])  =+    App (Var "not") (maple2AST e)++maple2AST (InertArgs Less es)  =+    foldl App (Var "less")  (map maple2AST es)++maple2AST (InertArgs Equal es) =+    foldl App (Var "equal") (map maple2AST es)++maple2AST (InertArgs NotEq es) =+    App (Var "not") (foldl App (Var "equal") (map maple2AST es))++maple2AST (InertArgs Power [x, InertNum Pos y]) =+    App (App (Var "^")  (maple2AST x)) (maple2AST (InertNum Pos y))+maple2AST (InertArgs Power [x, InertNum Neg (-1)]) =+    App (Var "recip")  (maple2AST x)+maple2AST (InertArgs Power [x, +                            InertArgs Rational+                            [InertNum Pos 1, InertNum Pos y]]) =+    App (App (Var "natroot") (maple2AST x)) (ULiteral . Nat $ y)++maple2AST (InertArgs Power [x, +                            InertArgs Rational+                            [InertNum Neg (-1), InertNum Pos y]]) =+    App (Var "recip")+        (App (App (Var "natroot") (maple2AST x)) (ULiteral . Nat $ y))++maple2AST (InertArgs Power [x, y]) =+    App (App (Var "**") (maple2AST x)) (maple2AST y)+maple2AST (InertArgs Rational [InertNum Pos x, InertNum Pos y]) =+    ULiteral . Prob $ fromInteger x % fromInteger y+maple2AST (InertArgs Rational [InertNum _ x, InertNum _ y]) =+    ULiteral . Real $ fromInteger x % fromInteger y++maple2AST x = error $ "Can't handle: " ++ show x++----------------------------------------------------------------++mapleDatum2AST :: Text -> InertExpr -> AST' Text+mapleDatum2AST h d = case (h, maple2DCode d) of+  ("pair", [x,y]) -> Pair x y+  ("unit", []   ) -> Unit+  _               -> error $ "TODO: mapleDatum2AST " ++ Text.unpack h+    +maple2Type :: InertExpr -> TypeAST'+maple2Type (InertArgs Func+            [InertName "HInt",+             InertArgs ExpSeq+             [InertArgs Func+              [InertName "Bound",+               InertArgs ExpSeq+               [InertName ">=",InertNum Pos 0]]]])+    = TypeVar "nat"+maple2Type (InertArgs Func+            [InertName "HInt",+             InertArgs ExpSeq []])+    = TypeVar "int"+maple2Type (InertArgs Func+            [InertName "HReal",+             InertArgs ExpSeq+             [InertArgs Func+              [InertName "Bound",+               InertArgs ExpSeq+               [InertName ">=",InertNum Pos 0]]]])+    = TypeVar "prob"+maple2Type (InertArgs Func+            [InertName "HReal",+             InertArgs ExpSeq []])+    = TypeVar "real"++maple2Type (InertArgs Func+            [InertName "HData",+             InertArgs ExpSeq+             [InertArgs Func+              [InertName "DatumStruct",+               InertArgs ExpSeq+               [InertName "unit",+                InertArgs List+                [InertArgs ExpSeq []]]]]])+     = TypeVar "unit"++maple2Type (InertArgs Func+            [InertName "HData",+             InertArgs ExpSeq+             [InertArgs Func+              [InertName "DatumStruct",+               InertArgs ExpSeq+               [InertName "true",+                InertArgs List+                [InertArgs ExpSeq []]]],+              InertArgs Func+              [InertName "DatumStruct",+               InertArgs ExpSeq+               [InertName "false",+                InertArgs List+                [InertArgs ExpSeq []]]]]])+     = TypeVar "bool"++maple2Type (InertArgs Func+            [InertName "HData",+             InertArgs ExpSeq+             [InertArgs Func+              [InertName "DatumStruct",+               InertArgs ExpSeq+               [InertName "pair",+                InertArgs List+                [InertArgs ExpSeq+                 [InertArgs Func+                  [InertName "Konst",+                   InertArgs ExpSeq [x]],+                  InertArgs Func+                  [InertName "Konst",+                   InertArgs ExpSeq [y]]]]]]]])+     = TypeApp "pair" (map maple2Type [x, y])++maple2Type (InertArgs Func+            [InertName "HArray",+             InertArgs ExpSeq+             [x]])+     = TypeApp "array" [maple2Type x]++maple2Type (InertArgs Func+            [InertName "HFunction",+             InertArgs ExpSeq+             [x, y]])+     = TypeFun (maple2Type x) (maple2Type y)++maple2Type (InertArgs Func+            [InertName "HMeasure",+             InertArgs ExpSeq+             [x]])+     = TypeApp "measure" [maple2Type x]++maple2Type x = error ("TODO: maple2Type " ++ show x)+++branch :: InertExpr -> Branch' Text+branch (InertArgs Func+        [InertName "Branch",+         InertArgs ExpSeq [pat, e]]) =+    Branch' (maple2Pattern pat) (maple2AST e)+++maple2Pattern :: InertExpr -> Pattern' Text+maple2Pattern (InertName "PWild") = PWild'+maple2Pattern (InertArgs Func+               [InertName "PVar",+                InertArgs ExpSeq+                [InertName x]]) = PVar' x+maple2Pattern (InertArgs Func+               [InertName "PDatum",+                InertArgs ExpSeq+                [InertName hint, args]]) =+    PData' (DV hint (maple2Patterns args))+maple2Pattern e = error $ "TODO: maple2AST{pattern} " ++ show e++maple2DCode :: InertExpr -> [AST' Text]+maple2DCode (InertArgs Func [InertName "Inl", InertArgs ExpSeq [e]]) = maple2DCode e+maple2DCode (InertArgs Func [InertName "Inr", InertArgs ExpSeq [e]]) = maple2DCode e+maple2DCode (InertArgs Func [InertName "Et" , InertArgs ExpSeq [InertArgs Func [InertName "Konst", InertArgs ExpSeq [x]], e]]) = maple2AST x : maple2DCode e+maple2DCode (InertName "Done") = []+maple2DCode e = error $ "maple2DCode: " ++ show e ++ " not InertExpr of a datum"++maple2Patterns :: InertExpr -> [Pattern' Text]+maple2Patterns (InertArgs Func [InertName "PInl", InertArgs ExpSeq [e]]) = maple2Patterns e+maple2Patterns (InertArgs Func [InertName "PInr", InertArgs ExpSeq [e]]) = maple2Patterns e+maple2Patterns (InertArgs Func [InertName "PEt" , InertArgs ExpSeq [InertArgs Func [InertName "PKonst", InertArgs ExpSeq [x]], e]]) = maple2Pattern x : maple2Patterns e+maple2Patterns (InertName "PDone") = []+maple2Patterns e = error $ "maple2Patterns: " ++ show e ++ " not InertExpr of a pattern"
+ haskell/Language/Hakaru/Parser/Parser.hs view
@@ -0,0 +1,539 @@+{-# LANGUAGE CPP, OverloadedStrings #-}+{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+module Language.Hakaru.Parser.Parser where++import Prelude hiding (Real)++#if __GLASGOW_HASKELL__ < 710+import           Data.Functor                  ((<$>), (<$))+import           Control.Applicative           (Applicative(..))+#endif+import qualified Control.Monad                 as M+import           Data.Functor.Identity+import           Data.Text                     (Text)+import qualified Data.Text                     as Text+import           Data.Ratio                    ((%))+import           Data.Char                     (digitToInt)+import           Text.Parsec                   hiding (Empty)+import           Text.Parsec.Text              () -- instances only+import           Text.Parsec.Indentation+import           Text.Parsec.Indentation.Char+import qualified Text.Parsec.Indentation.Token as ITok+import qualified Text.Parsec.Expr              as Ex+import qualified Text.Parsec.Token             as Tok++import Language.Hakaru.Parser.AST+++ops, types, names :: [String]+ops   = ["+","*","-","^", "**", ":",".", "<~","==", "=", "_", "<|>"]+types = ["->"]+names = ["def", "fn", "if", "else", "∞", "expect", "observe",+         "return", "match", "integrate", "summate", "product",+         "data", "import"]++type ParserStream    = IndentStream (CharIndentStream Text)+type Parser          = ParsecT     ParserStream () Identity+type Operator a      = Ex.Operator ParserStream () Identity a+type OperatorTable a = [[Operator a]]++style :: Tok.GenLanguageDef ParserStream st Identity+style = ITok.makeIndentLanguageDef $ Tok.LanguageDef+    { Tok.commentStart    = ""+    , Tok.commentEnd      = ""+    , Tok.nestedComments  = True+    , Tok.identStart      = letter <|> char '_'+    , Tok.identLetter     = alphaNum <|> oneOf "_'"+    , Tok.opStart         = oneOf "!$%&*+./<=>?@\\^|-~"+    , Tok.opLetter        = oneOf "!$%&*+./<=>?@\\^|-~"+    , Tok.caseSensitive   = True+    , Tok.commentLine     = "#"+    , Tok.reservedOpNames = ops ++ types+    , Tok.reservedNames   = names+    }++comments :: Parser ()+comments = string "#"+           *> manyTill anyChar newline+           *> return ()++emptyLine :: Parser ()+emptyLine = newline *> return ()++lexer :: Tok.GenTokenParser ParserStream () Identity+lexer = ITok.makeTokenParser style++whiteSpace :: Parser ()+whiteSpace = Tok.whiteSpace lexer++decimal :: Parser Integer+decimal = Tok.decimal lexer++integer :: Parser Integer+integer = Tok.integer lexer++float :: Parser Rational+float =  (decimal >>= fractExponent) <* whiteSpace+                  +fractFloat :: Integer -> Parser (Either Integer Rational)+fractFloat n  =  fractExponent n >>= return . Right++fractExponent   :: Integer -> Parser Rational+fractExponent n =  do{ fract <- fraction+                     ; expo  <- option 1 exponent'+                     ; return ((fromInteger n + fract)*expo)+                     }+                  <|>+                  do{ expo <- exponent'+                    ; return ((fromInteger n)*expo)+                    }++fraction        :: Parser Rational+fraction        =  do{ _ <- char '.'+                     ; digits <- many1 digit <?> "fraction"+                     ; return (foldr op 0 digits)+                     }+                  <?> "fraction"+                    where+                      op d f    = (f + fromIntegral (digitToInt d))/10++exponent'       :: Parser Rational+exponent'       =  do{ _ <- oneOf "eE"+                     ; f <- sign+                     ; e <- decimal <?> "exponent"+                     ; return (power (f e))+                     }+                  <?> "exponent"+                      where+                       power e  | e < 0      = 1.0/power(-e)+                                | otherwise  = fromInteger (10^e)+                       sign            =   (char '-' >> return negate)+                                       <|> (char '+' >> return id)+                                       <|> return id++parens :: Parser a -> Parser a+parens = Tok.parens lexer . localIndentation Any++braces :: Parser a -> Parser a+braces = Tok.parens lexer . localIndentation Any++brackets :: Parser a -> Parser a+brackets = Tok.brackets lexer . localIndentation Any++commaSep :: Parser a -> Parser [a]+commaSep = Tok.commaSep lexer++semiSep :: Parser a -> Parser [a]+semiSep = Tok.semiSep lexer++semiSep1 :: Parser a -> Parser [a]+semiSep1 = Tok.semiSep1 lexer++identifier :: Parser Text+identifier = M.liftM Text.pack $ Tok.identifier lexer++reserved :: String -> Parser ()+reserved = Tok.reserved lexer++reservedOp :: String -> Parser ()+reservedOp = Tok.reservedOp lexer++symbol :: Text -> Parser Text+symbol = M.liftM Text.pack . Tok.symbol lexer . Text.unpack++app1 :: Text -> AST' Text -> AST' Text+app1 s x@(WithMeta _ m) = WithMeta (Var s `App` x) m+app1 s x                = Var s `App` x++app2 :: Text -> AST' Text -> AST' Text -> AST' Text+app2 s x y = Var s `App` x `App` y++-- | Smart constructor for divide+divide :: AST' Text -> AST' Text -> AST' Text+divide (ULiteral x') (ULiteral y') = ULiteral (go x' y')+  where go :: Literal' -> Literal' -> Literal'+        go (Nat  x) (Nat  y) = Prob (x % y)+        go x        y        = Real (litToRat x / litToRat y)++        litToRat :: Literal' -> Rational+        litToRat (Nat  x) = toRational x+        litToRat (Int  x) = toRational x+        litToRat (Prob x) = toRational x+        litToRat (Real x) = toRational x+divide x y = NaryOp Prod [x, app1 "recip" y]++binop :: Text ->  AST' Text ->  AST' Text ->  AST' Text+binop s x y+    | s == "+"   = NaryOp Sum  [x, y]+    | s == "-"   = NaryOp Sum  [x, app1 "negate" y]+    | s == "*"   = NaryOp Prod [x, y]+    | s == "/"   = x `divide` y+    | s == "<"   = app2 "less"  x y+    | s == ">"   = app2 "less"  y x+    | s == "=="  = app2 "equal" x y+    | s == "<="  = NaryOp Or [ app2 "less"  x y+                             , app2 "equal" x y]+    | s == ">="  = NaryOp Or [ app2 "less"  y x+                             , app2 "equal" x y]+    | s == "&&"  = NaryOp And  [x, y]+    | s == "<|>" = Msum [x, y]+    | otherwise  = app2 s x y++binary :: String -> Ex.Assoc -> Operator (AST' Text)+binary s = Ex.Infix (binop (Text.pack s) <$ reservedOp s)++prefix :: String -> (a -> a) -> Operator a +prefix s f = Ex.Prefix (f <$ reservedOp s)++postfix :: Parser (a -> a) -> Operator a+postfix p = Ex.Postfix . chainl1 p . return $ flip (.)++table :: OperatorTable (AST' Text)+table =+    [ [ postfix array_index ]+    , [ prefix "+"  id ]+    , [ binary "^"  Ex.AssocRight+      , binary "**" Ex.AssocRight]+    , [ binary "*"  Ex.AssocLeft+      , binary "/"  Ex.AssocLeft]+    , [ binary "+"  Ex.AssocLeft+      , binary "-"  Ex.AssocLeft+      , prefix "-"  (app1 "negate")]+    -- TODO: add "<=", ">=", "/="+    -- TODO: do you *really* mean AssocLeft? Shouldn't they be non-assoc?+    , [ postfix ann_expr ]+    , [ binary "<|>" Ex.AssocRight]+    , [ binary "<"   Ex.AssocLeft+      , binary ">"   Ex.AssocLeft+      , binary "<="  Ex.AssocLeft+      , binary ">="  Ex.AssocLeft+      , binary "=="  Ex.AssocLeft]+    , [ binary "&&"  Ex.AssocLeft]]++unit_ :: Parser (AST' a)+unit_ = Unit <$ symbol "()"++empty_ :: Parser (AST' a)+empty_ = Empty <$ symbol "[]"++int :: Parser (AST' a)+int = do+    n <- integer+    return $+        if n < 0+        then ULiteral $ Int n+        else ULiteral $ Nat n++floating :: Parser (AST' a)+floating = do+    sign <- option '+' (oneOf "+-")+    n <- float+    return $+        case sign of+        '-' -> ULiteral $ Real (negate n)+        '+' -> ULiteral $ Prob n+        _   -> error "floating: the impossible happened"++inf_ :: Parser (AST' Text)+inf_ = reserved "∞" *> return Infinity'++var :: Parser (AST' Text)+var = Var <$> identifier++pairs :: Parser (AST' Text)+pairs = foldr1 Pair <$> parens (commaSep expr)++type_var :: Parser TypeAST'+type_var = TypeVar <$> identifier++type_app :: Parser TypeAST'+type_app = TypeApp <$> identifier <*> parens (commaSep type_expr)++type_fun :: Parser TypeAST'+type_fun =+    chainr1+        (    try type_app+         <|> try type_var+         <|> parens type_fun)+        (TypeFun <$ reservedOp "->")++type_expr :: Parser TypeAST'+type_expr = try type_fun+        <|> try type_app+        <|> try type_var+        <|> parens type_expr++ann_expr :: Parser (AST' Text -> AST' Text)+ann_expr = reservedOp "." *> (flip Ann <$> type_expr)++pdat_expr :: Parser (PDatum Text)+pdat_expr = DV <$> identifier <*> parens (commaSep pat_expr)++pat_expr :: Parser (Pattern' Text)+pat_expr =  try (PData' <$> pdat_expr)+        <|> (PData' <$> (DV "pair" <$> parens (commaSep pat_expr)))+        <|> (PWild' <$ reservedOp "_")+        <|> (PVar' <$> identifier)+++-- | Blocks are indicated by colons, and must be indented.+blockOfMany :: Parser a -> Parser [a]+blockOfMany p = do+    reservedOp ":"+    localIndentation Gt (many $ absoluteIndentation p)+++-- | Semiblocks are like blocks, but indentation is optional. Also,+-- there are only 'expr' semiblocks.+semiblockExpr :: Parser (AST' Text)+semiblockExpr = reservedOp ":" *> localIndentation Ge expr+++-- | Pseudoblocks seem like semiblocks, but actually they aren't+-- indented.+--+-- TODO: do we actually want this in our grammar, or did we really+-- mean to use 'semiblockExpr' instead?+pseudoblockExpr :: Parser (AST' Text)+pseudoblockExpr = reservedOp ":" *> expr+++branch_expr :: Parser (Branch' Text)+branch_expr = Branch' <$> pat_expr <*> semiblockExpr++match_expr :: Parser (AST' Text)+match_expr =+    reserved "match"+    *>  (Case+        <$> expr+        <*> blockOfMany branch_expr+        )++integrate_expr :: Parser (AST' Text)+integrate_expr =+    reserved "integrate"+    *> (Integrate+        <$> identifier+        <*  symbol "from"        +        <*> expr+        <*  symbol "to"+        <*> expr     +        <*> semiblockExpr+        )++summate_expr :: Parser (AST' Text)+summate_expr =+    reserved "summate"+    *> (Summate+        <$> identifier+        <*  symbol "from"        +        <*> expr+        <*  symbol "to"+        <*> expr     +        <*> semiblockExpr+        )++product_expr :: Parser (AST' Text)+product_expr =+    reserved "product"+    *> (Product+        <$> identifier+        <*  symbol "from"        +        <*> expr+        <*  symbol "to"+        <*> expr     +        <*> semiblockExpr+        )++expect_expr :: Parser (AST' Text)+expect_expr =+    reserved "expect"+    *> (Expect+        <$> identifier+        <*> expr+        <*> semiblockExpr+        )++observe_expr :: Parser (AST' Text)+observe_expr =+    reserved "observe"+    *> (Observe+        <$> expr+        <*> expr+        )++array_expr :: Parser (AST' Text)+array_expr =+    reserved "array"+    *> (Array+        <$> identifier+        <*  symbol "of"+        <*> expr+        <*> semiblockExpr+        )++array_index :: Parser (AST' Text -> AST' Text)+array_index = flip Index <$> brackets expr++array_literal :: Parser (AST' Text)+array_literal = checkEmpty <$> brackets (commaSep expr)+  where checkEmpty [] = Empty+        checkEmpty xs = Array "" (ULiteral . Nat . fromIntegral . length $ xs)+                        (go 0 xs)++        go _ []      = error "the impossible happened"+        go _ [x]     = x+        go n (x:xs)  = If (Var "equal" `App` (Var "") `App` (ULiteral $ Nat n))+                          x+                          (go (n + 1) xs)+                ++plate_expr :: Parser (AST' Text)+plate_expr =+    reserved "plate"+    *> (Plate+        <$> identifier+        <*  symbol "of"+        <*> expr+        <*> semiblockExpr+        )++chain_expr :: Parser (AST' Text)+chain_expr =+    reserved "chain"+    *> (Chain+        <$> identifier+        <*> expr+        <*> expr+        <*> semiblockExpr+        )+++if_expr :: Parser (AST' Text)+if_expr =+    reserved "if"+    *>  (If+        <$> localIndentation Ge expr+        <*> semiblockExpr+        <*  reserved "else"+        <*> semiblockExpr+        )++lam_expr :: Parser (AST' Text)+lam_expr =+    reserved "fn"+    *>  (Lam+        <$> identifier+        <*> type_expr+        <*> semiblockExpr+        )++bind_expr :: Parser (AST' Text)+bind_expr = Bind+    <$> identifier+    <*  reservedOp "<~"+    <*> expr+    <*> expr++let_expr :: Parser (AST' Text)+let_expr = Let+    <$> identifier+    <*  reservedOp "="+    <*> expr+    <*> expr++def_expr :: Parser (AST' Text)+def_expr = do+    reserved "def"+    name <- identifier+    vars <- parens (commaSep defarg)+    bodyTyp <- optionMaybe type_expr+    body    <- semiblockExpr+    let body' = foldr (\(var', varTyp) e -> Lam var' varTyp e) body vars+        typ   = foldr TypeFun <$> bodyTyp <*> return (map snd vars)+    Let name (maybe id (flip Ann) typ body')+        <$> expr -- the \"rest\"; i.e., where the 'def' is in scope++defarg :: Parser (Text, TypeAST')+defarg = (,) <$> identifier <*> type_expr++call_expr :: Parser (AST' Text)+call_expr =+    foldl App+        <$> (Var <$> identifier)+        <*> parens (commaSep expr)++return_expr :: Parser (AST' Text)+return_expr = do+    reserved "return" <|> reserved "dirac"+    Dirac <$> expr++term :: Parser (AST' Text)+term =  try if_expr+    <|> try return_expr+    <|> try lam_expr+    <|> try def_expr+    <|> try match_expr+    -- <|> try data_expr+    <|> try integrate_expr+    <|> try summate_expr+    <|> try product_expr+    <|> try expect_expr+    <|> try observe_expr+    <|> try array_expr+    <|> try plate_expr+    <|> try chain_expr+    <|> try let_expr+    <|> try bind_expr+    <|> try call_expr+    <|> try array_literal+    <|> try floating+    <|> try inf_+    <|> try unit_+    <|> try empty_+    <|> try int+    <|> try var+    <|> try pairs+    <|> parens expr+    <?> "an expression"++expr :: Parser (AST' Text)+expr = withPos (Ex.buildExpressionParser table (withPos term) <?> "an expression")+++indentConfig :: Text -> ParserStream+indentConfig =+    mkIndentStream 0 infIndentation True Ge . mkCharIndentStream++parseHakaru :: Text -> Either ParseError (AST' Text)+parseHakaru =+    runParser (skipMany (comments <|> emptyLine) *>+               expr <* eof) () "<input>" . indentConfig++parseHakaruWithImports :: Text -> Either ParseError (ASTWithImport' Text)+parseHakaruWithImports =+    runParser (skipMany (comments <|> emptyLine) *>+               exprWithImport <* eof) () "<input>" . indentConfig++withPos :: Parser (AST' a) -> Parser (AST' a)+withPos x = do+    s  <- getPosition+    x' <- x+    e  <- getPosition+    return $ WithMeta x' (SourceSpan s e)++data_expr :: Parser (AST' Text)+data_expr =+    reserved "data"+    *>  (Data+        <$> identifier+        <*  parens (commaSep identifier) -- TODO: why throw them away?+        <*> blockOfMany (try type_app <|> type_var)+        )++import_expr :: Parser (Import Text)+import_expr =+    reserved "import" *> (Import <$> identifier)++exprWithImport :: Parser (ASTWithImport' Text)+exprWithImport = ASTWithImport' <$> (many import_expr) <*> expr
+ haskell/Language/Hakaru/Parser/SymbolResolve.hs view
@@ -0,0 +1,586 @@+{-# LANGUAGE CPP+           , OverloadedStrings+           , DataKinds+           , KindSignatures+           , GADTs+           #-}+{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+module Language.Hakaru.Parser.SymbolResolve where++import Data.Text hiding (concat, map, maximum, foldr1, singleton)+#if __GLASGOW_HASKELL__ < 710+import Data.Functor                     ((<$>))+import Control.Applicative              ((<*>))+#endif+import Control.Monad.Trans.State.Strict (State, state, evalState)++import qualified Data.Number.Nat                 as N+import qualified Data.IntMap                     as IM+import           Data.Foldable                   as F+import           Data.Ratio+import           Data.Proxy                      (KProxy(..))+import           Data.List.NonEmpty              as L (NonEmpty(..), fromList)+import           Language.Hakaru.Types.Sing+import           Language.Hakaru.Types.Coercion+import           Language.Hakaru.Types.DataKind  hiding (Symbol)+import           Language.Hakaru.Types.HClasses+import qualified Language.Hakaru.Syntax.AST      as T+import           Language.Hakaru.Syntax.ABT+import           Language.Hakaru.Syntax.IClasses+import           Language.Hakaru.Syntax.Variable ()+import qualified Language.Hakaru.Parser.AST   as U+import           Language.Hakaru.Evaluation.Coalesce (coalesce)++data Symbol a+    = TLam (a -> Symbol a)+    | TNeu a++data Symbol' a+    = TLam' ([a] -> a)+    | TNeu' a++singleton :: a -> L.NonEmpty a+singleton x = x :| []++primPat :: [(Text, Symbol' U.Pattern)]+primPat =+    [ ("left",    TLam' $ \ [a] ->+        U.PDatum "left" . U.PInl $+            U.PKonst a `U.PEt` U.PDone)+    , ("right",   TLam' $ \ [b] ->+        U.PDatum "right" . U.PInr . U.PInl $+            U.PKonst b `U.PEt` U.PDone)+    , ("true",    TNeu' . U.PDatum "true"  . U.PInl $ U.PDone)+    , ("false",   TNeu' . U.PDatum "false" . U.PInr . U.PInl $ U.PDone)+    , ("unit",    TNeu' . U.PDatum "unit"  . U.PInl $ U.PDone)+    , ("pair",    TLam' $ \es -> F.foldr1 pairPat es)+    , ("just",    TLam' $ \ [a] ->+        U.PDatum "just" . U.PInr . U.PInl $+            U.PKonst a `U.PEt` U.PDone)+    , ("nothing", TLam' $ \ [] ->+        U.PDatum "nothing" . U.PInl $ U.PDone)+    ]++pairPat :: U.Pattern -> U.Pattern -> U.Pattern+pairPat a b =+    U.PDatum "pair" .  U.PInl $+    U.PKonst a `U.PEt` U.PKonst b `U.PEt` U.PDone++primTypes :: [(Text, Symbol' U.SSing)]+primTypes = +    [ ("nat",     TNeu' $ U.SSing SNat)+    , ("int",     TNeu' $ U.SSing SInt)+    , ("prob",    TNeu' $ U.SSing SProb)+    , ("real",    TNeu' $ U.SSing SReal)+    , ("unit",    TNeu' $ U.SSing sUnit)+    , ("bool",    TNeu' $ U.SSing sBool)+    , ("array",   TLam' $ \ [U.SSing a] -> U.SSing $ SArray a)+    , ("measure", TLam' $ \ [U.SSing a] -> U.SSing $ SMeasure a)+    , ("either",  TLam' $ \ [U.SSing a, U.SSing b] -> U.SSing $ sEither a b)+    , ("pair",    TLam' $ \ [U.SSing a, U.SSing b] -> U.SSing $ sPair a b)+    , ("maybe",   TLam' $ \ [U.SSing a] -> U.SSing $ sMaybe a)+    ]++t2 :: (U.AST -> U.AST -> U.AST) -> Symbol U.AST+t2 f = TLam $ \a -> TLam $ \b -> TNeu (f a b)++t3 :: (U.AST -> U.AST -> U.AST -> U.AST) -> Symbol U.AST+t3 f = TLam $ \a -> TLam $ \b -> TLam $ \c -> TNeu (f a b c)++type SymbolTable = [(Text, Symbol U.AST)]++primTable :: SymbolTable+primTable =+    [-- Datatype constructors+     ("left",        primLeft)+    ,("right",       primRight)+    ,("just",        primJust)+    ,("nothing",     primNothing)+    ,("true",        TNeu $ true_)+    ,("false",       TNeu $ false_)+     -- Coercions+    ,("int2nat",     primUnsafe cNat2Int)+    ,("int2real",    primCoerce cInt2Real)+    ,("prob2real",   primCoerce cProb2Real)+    ,("real2prob",   primUnsafe cProb2Real)+    ,("nat2real",    primCoerce cNat2Real)+    ,("nat2prob",    primCoerce cNat2Prob)+    ,("nat2int",     primCoerce cNat2Int)+     -- Measures+    ,("lebesgue",    TNeu $ syn $ U.MeasureOp_ (U.SomeOp T.Lebesgue) [])+    ,("counting",    TNeu $ syn $ U.MeasureOp_ (U.SomeOp T.Counting) [])+    ,("uniform",     primMeasure2 (U.SomeOp T.Uniform))+    ,("normal",      primMeasure2 (U.SomeOp T.Normal))+    ,("poisson",     primMeasure1 (U.SomeOp T.Poisson))+    ,("gamma",       primMeasure2 (U.SomeOp T.Gamma))+    ,("beta",        primMeasure2 (U.SomeOp T.Beta))+    ,("categorical", primMeasure1 (U.SomeOp T.Categorical))+    ,("bern",        primBern)+    ,("factor",      primFactor)+    ,("weight",      primWeight)+    ,("dirac",       TLam $ TNeu . syn . U.Dirac_)+    ,("reject",      TNeu $ syn U.Reject_)+    -- PrimOps+    ,("not",         primPrimOp1 U.Not)+    ,("pi",          primPrimOp0 U.Pi)+    ,("**",          primPrimOp2 U.RealPow)+    ,("cos",         primPrimOp1 U.Cos)+    ,("exp",         primPrimOp1 U.Exp)+    ,("log",         primPrimOp1 U.Log)+    ,("inf",         primPrimOp0 U.Infinity)+    ,("gammaFunc",   primPrimOp1 U.GammaFunc)+    ,("betaFunc",    primPrimOp2 U.BetaFunc)+    ,("equal",       primPrimOp2 U.Equal)+    ,("less",        primPrimOp2 U.Less)+    ,("negate",      primPrimOp1 U.Negate)+    ,("abs",         primPrimOp1 U.Abs)+    ,("signum",      primPrimOp1 U.Signum)+    ,("recip",       primPrimOp1 U.Recip)+    ,("^",           primPrimOp2 U.NatPow)+    ,("natroot",     primPrimOp2 U.NatRoot)+    ,("sqrt",        TLam $ \x -> TNeu . syn $ U.PrimOp_ U.NatRoot [x, two])+    ,("erf",         primPrimOp1 U.Erf)+    ,("sin",         primPrimOp1 U.Sin)+    ,("cos",         primPrimOp1 U.Cos)+    ,("tan",         primPrimOp1 U.Tan)+    ,("asin",        primPrimOp1 U.Asin)+    ,("acos",        primPrimOp1 U.Acos)+    ,("atan",        primPrimOp1 U.Atan)+    ,("sinh",        primPrimOp1 U.Sinh)+    ,("cosh",        primPrimOp1 U.Cosh)+    ,("tanh",        primPrimOp1 U.Tanh)+    ,("asinh",       primPrimOp1 U.Asinh)+    ,("acosh",       primPrimOp1 U.Acosh)+    ,("atanh",       primPrimOp1 U.Atanh)+    -- ArrayOps+    ,("size",        TLam $ \x -> TNeu . syn $ U.ArrayOp_ U.Size [x])+    ,("reduce",      t3 $ \x y z -> syn $ U.ArrayOp_ U.Reduce [x, y, z])+    -- NaryOps+    ,("min",         t2 $ \x y -> syn $ U.NaryOp_ U.Min [x, y])+    ,("max",         t2 $ \x y -> syn $ U.NaryOp_ U.Max [x, y])+    ]++primPrimOp0, primPrimOp1, primPrimOp2 :: U.PrimOp -> Symbol U.AST+primPrimOp0 a = TNeu . syn $ U.PrimOp_ a []+primPrimOp1 a = TLam $ \x -> TNeu . syn $ U.PrimOp_ a [x]+primPrimOp2 a = t2 $ \x y ->        syn $ U.PrimOp_ a [x, y]++primMeasure1 :: U.SomeOp T.MeasureOp -> Symbol U.AST+primMeasure1 m = TLam $ \x -> TNeu . syn $ U.MeasureOp_ m [x]++primMeasure2 :: U.SomeOp T.MeasureOp -> Symbol U.AST+primMeasure2 m = t2 $ \x y -> syn $ U.MeasureOp_ m [x, y]++primCoerce :: Coercion a b -> Symbol U.AST+primCoerce c = TLam $ TNeu . syn . U.CoerceTo_  (Some2 c)++primUnsafe :: Coercion a b -> Symbol U.AST+primUnsafe c = TLam $ TNeu . syn . U.UnsafeTo_  (Some2 c)++cProb2Real :: Coercion 'HProb 'HReal+cProb2Real = signed++cNat2Prob :: Coercion 'HNat 'HProb+cNat2Prob = continuous++cNat2Int  :: Coercion 'HNat 'HInt+cNat2Int  = signed++cInt2Real  :: Coercion 'HInt 'HReal+cInt2Real  = continuous++cNat2Real :: Coercion 'HNat 'HReal+cNat2Real = CCons (Signed HRing_Int) continuous++unit_ :: U.AST+unit_ =+    syn $ U.Ann_ (U.SSing sUnit)+                 (syn $ U.Datum_ (U.Datum "unit" . U.Inl $ U.Done))++true_, false_ :: U.AST+true_  =+    syn $ U.Ann_ (U.SSing sBool)+                 (syn $ U.Datum_ . U.Datum "true"  . U.Inl $ U.Done)++false_ =+    syn $ U.Ann_ (U.SSing sBool)+                 (syn $ U.Datum_ . U.Datum "false" . U.Inr . U.Inl $ U.Done)++unsafeFrom_ :: U.AST -> U.AST+unsafeFrom_ = syn . U.UnsafeTo_ (Some2 $ CCons (Signed HRing_Real) CNil)++primLeft, primRight :: Symbol U.AST+primLeft =+    TLam $ TNeu . syn . U.Datum_ .+        U.Datum "left" . U.Inl . (`U.Et` U.Done) . U.Konst+primRight =+    TLam $ TNeu . syn . U.Datum_ .+        U.Datum "right" . U.Inr . U.Inl . (`U.Et` U.Done) . U.Konst++primJust, primNothing :: Symbol U.AST+primJust =+    TLam $ TNeu . syn . U.Datum_ .+        U.Datum "just" . U.Inr . U.Inl . (`U.Et` U.Done) . U.Konst+primNothing =+    TNeu . syn . U.Datum_ .+        U.Datum "nothing" . U.Inl $ U.Done++primWeight, primFactor, primBern :: Symbol U.AST+primWeight = t2 $ \w m -> syn $ U.Superpose_ (singleton (w, m))+primFactor = TLam $ \w -> TNeu . syn . U.Superpose_ $+              singleton (w, syn $ U.Dirac_ unit_)+primBern   =+    TLam $ \p -> TNeu . syn . U.Superpose_ . L.fromList $+        [ (p, syn $ U.Dirac_ true_)+        , (unsafeFrom_ . syn $ U.NaryOp_ U.Sum+            [ syn $ U.Literal_ (Some1 $ T.LReal 1.0)+            , syn $ U.PrimOp_ U.Negate [p]+            ]+            , syn $ U.Dirac_ false_)+        ]++two :: U.AST+two = syn . U.Literal_ . U.val . U.Nat $ 2++gensym :: Text -> State Int U.Name+gensym s = state $ \i -> (U.Name (N.unsafeNat i) s, i + 1)++mkSym  :: U.Name -> Symbol U.AST+mkSym (U.Name i t) = TNeu $ var (Variable t i U.SU)++insertSymbol :: U.Name -> SymbolTable -> SymbolTable+insertSymbol n@(U.Name _ name) sym = (name, mkSym n) : sym++insertSymbols :: [U.Name] -> SymbolTable -> SymbolTable+insertSymbols []     sym = sym+insertSymbols (n:ns) sym = insertSymbols ns (insertSymbol n sym)+++resolveBinder+    :: SymbolTable+    -> Text+    -> U.AST' Text+    -> U.AST' Text+    -> (Symbol U.AST+        -> U.AST' (Symbol U.AST)+        -> U.AST' (Symbol U.AST)+        -> U.AST' (Symbol U.AST))+    -> State Int (U.AST' (Symbol U.AST))+resolveBinder symbols name e1 e2 f = do+    name' <- gensym name+    f (mkSym name')+        <$> symbolResolution symbols e1+        <*> symbolResolution (insertSymbol name' symbols) e2        +    ++-- TODO: clean up by merging the @Reader (SymbolTable)@ and @State Int@ monads+-- | Figure out symbols and types.+symbolResolution+    :: SymbolTable+    -> U.AST' Text+    -> State Int (U.AST' (Symbol U.AST))+symbolResolution symbols ast =+    case ast of+    U.Var name ->+        case lookup name symbols of+        Nothing -> (U.Var . mkSym) <$> gensym name+        Just a  -> return $ U.Var a++    U.Lam name typ x -> do+        name' <- gensym name+        U.Lam (mkSym name') typ+            <$> symbolResolution (insertSymbol name' symbols) x++    U.App f x -> U.App+        <$> symbolResolution symbols f+        <*> symbolResolution symbols x++    U.Let name e1 e2    -> resolveBinder symbols name e1 e2 U.Let+    U.If e1 e2 e3       -> U.If+        <$> symbolResolution symbols e1+        <*> symbolResolution symbols e2+        <*> symbolResolution symbols e3++    U.Ann e typ         -> (`U.Ann` typ) <$> symbolResolution symbols e+    U.Infinity'         -> return $ U.Infinity'+    U.ULiteral v        -> return $ U.ULiteral v++    U.Integrate  name e1 e2 e3 -> do       +        name' <- gensym name+        U.Integrate (mkSym name')+            <$> symbolResolution symbols e1+            <*> symbolResolution symbols e2+            <*> symbolResolution (insertSymbol name' symbols) e3     ++    U.Summate    name e1 e2 e3 -> do       +        name' <- gensym name+        U.Summate (mkSym name')+            <$> symbolResolution symbols e1+            <*> symbolResolution symbols e2+            <*> symbolResolution (insertSymbol name' symbols) e3     ++    U.Product    name e1 e2 e3 -> do       +        name' <- gensym name+        U.Product (mkSym name')+            <$> symbolResolution symbols e1+            <*> symbolResolution symbols e2+            <*> symbolResolution (insertSymbol name' symbols) e3     ++    U.NaryOp op es      -> U.NaryOp op+        <$> mapM (symbolResolution symbols) es++    U.Unit              -> return $ U.Unit+    U.Empty             -> return $ U.Empty+    U.Pair e1 e2        -> U.Pair+        <$> symbolResolution symbols e1+        <*> symbolResolution symbols e2++    U.Array name e1 e2  -> resolveBinder symbols name e1 e2 U.Array++    U.Index a i -> U.Index+        <$> symbolResolution symbols a+        <*> symbolResolution symbols i++    U.Case e1 bs -> U.Case+        <$> symbolResolution symbols e1+        <*> mapM (symbolResolveBranch symbols) bs++    U.Dirac  e1            -> U.Dirac <$> symbolResolution symbols e1+    U.Bind   name e1 e2    -> resolveBinder symbols name e1 e2 U.Bind+    U.Plate  name e1 e2    -> resolveBinder symbols name e1 e2 U.Plate+    U.Expect name e1 e2    -> resolveBinder symbols name e1 e2 U.Expect+    U.Chain  name e1 e2 e3 -> do       +        name' <- gensym name+        U.Chain (mkSym name')+            <$> symbolResolution symbols e1+            <*> symbolResolution symbols e2+            <*> symbolResolution (insertSymbol name' symbols) e3     +    U.Observe e1 e2        -> U.Observe+        <$> symbolResolution symbols e1+        <*> symbolResolution symbols e2++    U.Msum es -> U.Msum <$> mapM (symbolResolution symbols) es++    U.Data   _name _typ -> error "TODO: symbolResolution{U.Data}"+    U.WithMeta a meta -> U.WithMeta+        <$> symbolResolution symbols a+        <*> return meta+++symbolResolveBranch+    :: SymbolTable+    -> U.Branch' Text+    -> State Int (U.Branch' (Symbol U.AST))+symbolResolveBranch symbols (U.Branch' pat ast) = do+    (pat', names) <- symbolResolvePat pat+    ast' <- symbolResolution (insertSymbols names symbols) ast+    return $ U.Branch'' pat' ast'+symbolResolveBranch _ _ =+    error "TODO: symbolResolveBranch{U.Branch''}"+++symbolResolvePat+    :: U.Pattern' Text+    -> State Int (U.Pattern' U.Name, [U.Name])+symbolResolvePat (U.PVar' "true") =+    return (U.PData' (U.DV "true" []), [])+symbolResolvePat (U.PVar' "false") =+    return (U.PData' (U.DV "false" []), [])+symbolResolvePat (U.PVar' name)  = do+    name' <- gensym name+    return (U.PVar' name', [name'])+symbolResolvePat U.PWild' =+    return (U.PWild', [])+symbolResolvePat (U.PData' (U.DV name args)) = do+    args' <- mapM symbolResolvePat args+    let (args'', names) = unzip args'+    return $ (U.PData' (U.DV name args''), F.concat names)+++-- | Make AST and give unique names for variables.+--+-- The logic here is to do normalization by evaluation for our+-- primitives. App inspects its first argument to see if it should+-- do something special. Otherwise App behaves as normal.+normAST :: U.AST' (Symbol U.AST) -> U.AST' (Symbol U.AST)+normAST ast =+    case ast of+    U.Var a           -> U.Var a+    U.Lam name typ f  -> U.Lam name typ (normAST f)+    U.App f x ->+        let x' = normAST x in+        case normAST f of+        U.Var (TLam f)      -> U.Var $ f (makeAST x')+        f'                  -> U.App f' x'++    U.Let name e1 e2          -> U.Let name (normAST e1) (normAST e2)+    U.If e1 e2 e3             -> U.If (normAST e1) (normAST e2) (normAST e3)+    U.Ann e typ1              -> U.Ann (normAST e) typ1+    U.Infinity'               -> U.Infinity'+    U.Integrate name e1 e2 e3 -> U.Integrate name (normAST e1) (normAST e2) (normAST e3)+    U.Summate   name e1 e2 e3 -> U.Summate   name (normAST e1) (normAST e2) (normAST e3)+    U.Product   name e1 e2 e3 -> U.Product   name (normAST e1) (normAST e2) (normAST e3)+    U.ULiteral v              -> U.ULiteral v+    U.NaryOp op es            -> U.NaryOp op (map normAST es)+    U.Unit                    -> U.Unit+    U.Empty                   -> U.Empty+    U.Pair e1 e2              -> U.Pair (normAST e1) (normAST e2)+    U.Array  name e1 e2       -> U.Array name (normAST e1) (normAST e2)+    U.Index       e1 e2       -> U.Index (normAST e1) (normAST e2)    +    U.Case        e1 e2       -> U.Case  (normAST e1) (map branchNorm e2)+    U.Dirac       e1          -> U.Dirac (normAST e1)+    U.Bind   name e1 e2       -> U.Bind   name (normAST e1) (normAST e2)+    U.Plate  name e1 e2       -> U.Plate  name (normAST e1) (normAST e2)+    U.Chain  name e1 e2 e3    -> U.Chain  name (normAST e1) (normAST e2) (normAST e3)+    U.Expect name e1 e2       -> U.Expect name (normAST e1) (normAST e2)+    U.Observe     e1 e2       -> U.Observe (normAST e1) (normAST e2)+    U.Msum es                 -> U.Msum (map normAST es)+    U.Data name typ           -> U.Data name typ+    U.WithMeta a meta         -> U.WithMeta (normAST a) meta++branchNorm :: U.Branch' (Symbol U.AST) -> U.Branch' (Symbol U.AST)+branchNorm (U.Branch'  pat e2') = U.Branch'  pat (normAST e2')+branchNorm (U.Branch'' pat e2') = U.Branch'' pat (normAST e2')++collapseSuperposes :: [U.AST] -> U.AST+collapseSuperposes es = syn $ U.Superpose_ (fromList $ F.concatMap go es)+    where+    go :: U.AST -> [(U.AST, U.AST)]+    go e = caseVarSyn e (\x -> [(prob_ 1, var x)]) $ \t ->+              case t of+              U.Superpose_ es' -> F.toList es'+              _                -> [(prob_ 1, e)]++    prob_ :: Ratio Integer -> U.AST+    prob_ = syn . U.Literal_ . U.val . U.Prob++makeType :: U.TypeAST' -> U.SSing+makeType (U.TypeVar t) =+    case lookup t primTypes of+    Just (TNeu' t') -> t'+    _               -> error $ "Type " ++ show t ++ " is not a primitive"+makeType (U.TypeFun f x) =+    case (makeType f, makeType x) of+    (U.SSing f', U.SSing x') -> U.SSing $ SFun f' x'+makeType (U.TypeApp f args) =+    case lookup f primTypes of+    Just (TLam' f') -> f' (map makeType args)+    _               -> error $ "Type " ++ show f ++ " is not a primitive"+++makePattern :: U.Pattern' U.Name -> U.Pattern+makePattern U.PWild'        = U.PWild+makePattern (U.PVar' name)  =+    case lookup (U.hintID name) primPat of+    Just (TLam' _)  -> error "TODO{makePattern:PVar:TLam}"+    Just (TNeu' p') -> p'+    Nothing         -> U.PVar name+makePattern (U.PData' (U.DV name args)) =+    case lookup name primPat of+    Just (TLam' f') -> f' (map makePattern args)+    Just (TNeu' p') -> p'+    Nothing -> error $ "Data constructor " ++ show name ++ " not found"++makeBranch :: U.Branch' (Symbol U.AST) -> U.Branch+makeBranch (U.Branch'' pat ast) = U.Branch_ (makePattern pat) (makeAST ast)+makeBranch (U.Branch'  _   _)   = error "branch was not symbol resolved"++makeTrue, makeFalse :: U.AST' (Symbol U.AST) -> U.Branch+makeTrue  e =+    U.Branch_ (makePattern (U.PData' (U.DV "true"  []))) (makeAST e)+makeFalse e =+    U.Branch_ (makePattern (U.PData' (U.DV "false" []))) (makeAST e)+        +        +makeAST :: U.AST' (Symbol U.AST) -> U.AST+makeAST ast =+    case ast of+    -- TODO: Add to Symbol datatype: gensymed names and types+    -- for primitives (type for arg on lam, return type in neu)+    U.Var (TLam _) ->+        error "makeAST: Passed primitive with wrong number of arguments"+    U.Var (TNeu e) -> e+    U.Lam s typ e1 ->+        withName "U.Lam" s $ \name ->+            syn $ U.Lam_ (makeType typ) (bind name $ makeAST e1)+    U.App e1 e2 ->+        syn $ U.App_ (makeAST e1) (makeAST e2)+    U.Let s e1 e2 ->+        withName "U.Let" s $ \name ->+            syn $ U.Let_ (makeAST e1) (bind name $ makeAST e2)+    U.If e1 e2 e3 ->+        syn $ U.Case_ (makeAST e1) [(makeTrue e2), (makeFalse e3)]+    U.Ann e typ       -> syn $ U.Ann_ (makeType typ) (makeAST e)+    U.Infinity'       -> syn $ U.PrimOp_ U.Infinity []+    U.ULiteral v      -> syn $ U.Literal_  (U.val v)+    U.NaryOp op es    -> syn $ U.NaryOp_ op (map makeAST es)+    U.Unit            -> unit_+    U.Empty           -> syn $ U.Empty_+    U.Pair e1 e2      -> syn $ U.Pair_ (makeAST e1) (makeAST e2)+    U.Array s e1 e2 ->+        withName "U.Array" s $ \name ->+            syn $ U.Array_ (makeAST e1) (bind name $ makeAST e2)+    U.Index e1 e2     -> syn $ U.ArrayOp_ U.Index_ [(makeAST e1), (makeAST e2)]+    U.Case e bs       -> syn $ U.Case_ (makeAST e) (map makeBranch bs)+    U.Dirac e1        -> syn $ U.Dirac_ (makeAST e1)+    U.Bind s e1 e2 ->+        withName "U.Bind" s $ \name ->+            syn $ U.MBind_ (makeAST e1) (bind name $ makeAST e2)+    U.Plate s e1 e2 ->+        withName "U.Plate" s $ \name ->+            syn $ U.Plate_ (makeAST e1) (bind name $ makeAST e2)+    U.Chain s e1 e2 e3 ->+        withName "U.Chain" s $ \name ->+            syn $ U.Chain_ (makeAST e1) (makeAST e2) (bind name $ makeAST e3)+    U.Integrate s e1 e2 e3 ->+        withName "U.Integrate" s $ \name ->+            syn $ U.Integrate_ (makeAST e1) (makeAST e2) (bind name $ makeAST e3)+    U.Summate s e1 e2 e3 ->+        withName "U.Summate" s $ \name ->+            syn $ U.Summate_ (makeAST e1) (makeAST e2) (bind name $ makeAST e3)+    U.Product s e1 e2 e3 ->+        withName "U.Product" s $ \name ->+            syn $ U.Product_ (makeAST e1) (makeAST e2) (bind name $ makeAST e3)+    U.Expect s e1 e2 ->+        withName "U.Expect" s $ \name ->+            syn $ U.Expect_ (makeAST e1) (bind name $ makeAST e2)+    U.Observe e1 e2  -> syn $ U.Observe_ (makeAST e1) (makeAST e2)+    U.Msum es -> collapseSuperposes (map makeAST es)+    +    U.Data   _name _typ -> error "TODO: makeAST{U.Data}"+    U.WithMeta a meta -> withMetadata meta (makeAST a)++    where+    withName :: String -> Symbol U.AST -> (Variable 'U.U -> r) -> r+    withName fun s k =+        case s of+        TNeu e -> caseVarSyn e k (error $ "makeAST: bad " ++ fun)+        _      -> error $ "makeAST: bad " ++ fun++resolveAST :: U.AST' Text -> U.AST+resolveAST ast =+    coalesce .+    makeAST  .+    normAST $+    evalState (symbolResolution primTable ast) 0++resolveAST'+    :: [U.Name]+    -> U.AST' Text+    -> U.AST+resolveAST' syms ast =+    coalesce .+    makeAST  .+    normAST  $+    evalState (symbolResolution+        (insertSymbols syms primTable) ast)+        (nextVarID_ syms)+    where+    nextVarID_ [] = N.fromNat 0+    nextVarID_ xs = N.fromNat . (1+) . F.maximum $ map U.nameID xs++makeName :: SomeVariable ('KProxy :: KProxy Hakaru) -> U.Name+makeName (SomeVariable (Variable hint vID _)) = U.Name vID hint++fromVarSet :: VarSet ('KProxy :: KProxy Hakaru) -> [U.Name]+fromVarSet (VarSet xs) = map makeName (IM.elems xs)
+ haskell/Language/Hakaru/Pretty/Concrete.hs view
@@ -0,0 +1,703 @@+{-# LANGUAGE GADTs+           , KindSignatures+           , DataKinds+           , ScopedTypeVariables+           , PatternGuards+           , Rank2Types+           , TypeOperators+           , FlexibleContexts+           , UndecidableInstances+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.05.28+-- |+-- Module      :  Language.Hakaru.Pretty.Concrete+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+--+----------------------------------------------------------------+module Language.Hakaru.Pretty.Concrete+    (+    -- * The user-facing API+      pretty+    , prettyPrec+    , prettyType+    , prettyAssoc+    , prettyPrecAssoc+    , prettyValue+    -- * Helper functions (semi-public internal API)+    ) where++import           System.Console.ANSI+import           Text.PrettyPrint                (Doc, (<>), (<+>))+import qualified Text.PrettyPrint                as PP+import qualified Data.Foldable                   as F+import qualified Data.List.NonEmpty              as L+import qualified Data.Text                       as Text++-- Because older versions of "Data.Foldable" do not export 'null' apparently...+import qualified Data.Sequence                   as Seq+import qualified Data.Vector                     as V+import           Data.Ratio++import           Data.Number.Natural  (fromNatural, fromNonNegativeRational)+import           Data.Number.Nat+import qualified Data.Number.LogFloat            as LF++import Language.Hakaru.Syntax.IClasses (fmap11, foldMap11, jmEq1, TypeEq(..))+import Language.Hakaru.Types.DataKind+import Language.Hakaru.Types.Sing+import Language.Hakaru.Types.Coercion+import Language.Hakaru.Types.HClasses+import Language.Hakaru.Syntax.AST+import Language.Hakaru.Syntax.Datum+import Language.Hakaru.Syntax.Value+import Language.Hakaru.Syntax.ABT+import Language.Hakaru.Pretty.Haskell+    (ppRatio, prettyAssoc, prettyPrecAssoc, Associativity(..))++----------------------------------------------------------------+-- | Pretty-print a term.+pretty :: (ABT Term abt) => abt '[] a -> Doc+pretty = prettyPrec 0+++-- | Pretty-print a term at a given precendence level.+prettyPrec :: (ABT Term abt) => Int -> abt '[] a -> Doc+prettyPrec p = toDoc . prettyPrec_ p . LC_++----------------------------------------------------------------+class Pretty (f :: Hakaru -> *) where+    -- | A polymorphic variant if 'prettyPrec', for internal use.+    prettyPrec_ :: Int -> f a -> Docs++type Docs = [Doc] ++-- So far as I can tell from the documentation, if the input is a singleton list then the result is the same as that singleton.+toDoc :: Docs -> Doc+toDoc = PP.cat++-- | Color a Doc+color :: Color -> Doc -> Doc+color c d =+    PP.text (setSGRCode [SetColor Foreground Dull c])+    <> d+    <> PP.text (setSGRCode [Reset])++keyword :: Doc -> Doc+keyword = color Red++-- | Pretty-print a variable.+ppVariable :: Variable (a :: Hakaru) -> Doc+ppVariable x = hint+    where+    hint+        | Text.null (varHint x) = PP.char 'x'  <> (PP.int . fromNat . varID) x -- We used to use '_' but...+        | otherwise             = (PP.text . Text.unpack . varHint) x++ppVariableWithType :: Variable (a :: Hakaru) -> (Doc, Doc)+ppVariableWithType x = (hint, (prettyType 0 . varType) x)+    where+    hint+        | Text.null (varHint x) = PP.char 'x' <> (PP.int . fromNat . varID) x -- We used to use '_' but...+        | otherwise             = (PP.text . Text.unpack . varHint) x++-- BUG: we still use this in a few places. I'm pretty sure they should all actually be 'ppBinder2', in which case we can delete this function and just use that one.+ppBinder :: (ABT Term abt) => abt xs a -> Docs+ppBinder e =+    case go [] (viewABT e) of+    ([],  body) -> body+    (vars,body) -> PP.char '\\' <> PP.sep vars <+> PP.text "-> " : body+    where+    go :: (ABT Term abt) => [Doc] -> View (Term abt) xs a -> ([Doc],Docs)+    go xs (Bind x v) = go (ppVariable x : xs) v+    go xs (Var  x)   = (reverse xs, [ppVariable x])+    go xs (Syn  t)   = (reverse xs, prettyPrec_ 0 (LC_ (syn t)))+++ppBinder2 :: (ABT Term abt) => abt xs a -> ([Doc], [Doc], Docs)+ppBinder2 e = unpackVarTypes $ go [] (viewABT e)+    where+    unpackVarTypes (varTypes, body) =+        (map fst varTypes, map snd varTypes, body)++    go :: (ABT Term abt) => [(Doc, Doc)] -> View (Term abt) xs a -> ([(Doc, Doc)],Docs)+    go xs (Bind x v) = go (ppVariableWithType x : xs) v+    go xs (Var  x)   = (reverse xs, [ppVariable x])+    go xs (Syn  t)   = (reverse xs, prettyPrec_ 0 (LC_ (syn t)))+++-- TODO: since switching to ABT2, this instance requires -XFlexibleContexts; we should fix that if we can+-- BUG: since switching to ABT2, this instance requires -XUndecidableInstances; must be fixed!+instance (ABT Term abt) => Pretty (LC_ abt) where+  prettyPrec_ p (LC_ e) =+    caseVarSyn e ((:[]) . ppVariable) $ \t ->+        case t of+        o :$ es      -> ppSCon p o es+        NaryOp_ o es ->+            if Seq.null es then identityElement o+            else+                case o of+                  And      -> parens (p > 3)+                              . PP.punctuate (PP.text " && ")+                              . map (prettyPrec 3)+                              $ F.toList es+                  Or       -> parens (p > 2)+                              . PP.punctuate (PP.text " || ")+                              . map (prettyPrec 2)+                              $ F.toList es+                  Xor      -> parens (p > 0)+                              . PP.punctuate (PP.text " != ")+                              . map (prettyPrec 0)+                              $ F.toList es+                -- BUG: even though 'Iff' is associative (in Boolean algebras), we should not support n-ary uses in our *surface* syntax. Because it's too easy for folks to confuse "a <=> b <=> c" with "(a <=> b) /\ (b <=> c)".+                  Iff      -> [F.foldl1 (\a b -> toDoc $ ppFun p "iff" [a, b])+                                         (fmap (toDoc . ppArg) es)]+                  (Min  _) -> [F.foldl1 (\a b -> toDoc $ ppFun p "min" [a, b])+                                         (fmap (toDoc . ppArg) es)]+                  (Max  _) -> [F.foldl1 (\a b -> toDoc $ ppFun p "max" [a, b])+                                          (fmap (toDoc . ppArg) es)]+                  (Sum  _) -> case Seq.viewl es of+                                Seq.EmptyL -> [PP.text "0"]+                                (e' Seq.:< es') -> parens (p > 6) $+                                    F.foldl (\a b -> a ++ (ppNaryOpSum 6 b))+                                            [prettyPrec 6 e']+                                            es'+                  (Prod _) ->  case Seq.viewl es of+                                Seq.EmptyL -> [PP.text "1"]+                                (e' Seq.:< es') -> parens (p > 7) $+                                    F.foldl (\a b -> a ++ (ppNaryOpProd 7 b))+                                            [prettyPrec 7 e']+                                            es'++          where identityElement :: NaryOp a -> Docs+                identityElement And      = [PP.text "true"]+                identityElement Or       = [PP.text "false"]+                identityElement Xor      = [PP.text "false"]+                identityElement Iff      = [PP.text "true"]+                identityElement (Min  _) = error "min can not be used with no arguements"+                identityElement (Max  _) = error "max can not be used with no arguements"+                identityElement (Sum  _) = [PP.text "0"]+                identityElement (Prod _) = [PP.text "1"]++        Literal_ v    -> prettyPrec_ p v+        Empty_   _    -> [PP.text "empty"]+        Array_ e1 e2  ->+            let (vars, _, body) = ppBinder2 e2 in+            [ PP.text "array"+              <+> toDoc vars+              <+> PP.text "of"+              <+> toDoc (ppArg e1)+              <> PP.colon <> PP.space+            , PP.nest 1 (toDoc body)]++        Datum_ d      -> prettyPrec_ p (fmap11 LC_ d)+        Case_  e1 bs  -> parens True $+            -- TODO: should we also add hints to the 'Case_' constructor to know whether it came from 'if_', 'unpair', etc?+            [ PP.text "match"+              <+> (toDoc $ ppArg e1)+              <> PP.colon <> PP.space+            , PP.nest 1 (PP.vcat (map (toDoc . prettyPrec_ 0) bs))+            ]+        Superpose_ pes ->+            PP.punctuate (PP.text " <|> ") $ L.toList $ fmap ppWeight pes+          where ppWeight (w,m)+                    | (PP.render $ pretty w) == "1" =+                        toDoc $ ppArg m+                    | otherwise                 =+                        toDoc $ ppFun p "weight" [pretty w, pretty m]++        Reject_ typ -> [PP.text "reject." <+> prettyType 0 typ]++ppNaryOpSum+    :: forall abt a+    . (ABT Term abt)+    => Int+    -> abt '[] a+    -> Docs+ppNaryOpSum p e =+    caseVarSyn e (const $ prefixToTerm "+" e) $ \t ->+        case t of+        Literal_ (LInt  i) | i < 0 ->      prefixToTerm "-" (syn . Literal_ . LInt  . abs $ i)+        Literal_ (LReal i) | i < 0 ->      prefixToTerm "-" (syn . Literal_ . LReal . abs $ i)+        PrimOp_ (Negate _) :$ e1 :* End -> prefixToTerm "-" e1+        _ -> prefixToTerm "+" e+  where prefixToTerm :: forall a. String -> abt '[] a -> Docs+        prefixToTerm s e = [ PP.space <> PP.text s <> PP.space+                           , prettyPrec p e+                           ]++ppNaryOpProd+    :: forall abt a+    . (ABT Term abt)+    => Int+    -> abt '[] a+    -> Docs+ppNaryOpProd p e =+    caseVarSyn e (const $ prefixToTerm "*" e) $ \t ->+        case t of+        Literal_ (LProb i) | numerator i == 1 -> +          prefixToTerm "/" (syn . Literal_ . LProb . fromIntegral . denominator $ i)+        Literal_ (LReal i) | numerator i == 1 -> +          prefixToTerm "/" (syn . Literal_ . LReal . fromIntegral . denominator $ i)+        PrimOp_ (Recip _) :$ e1 :* End -> prefixToTerm "/" e1+        _ -> prefixToTerm "*" e+  where prefixToTerm :: forall a. String -> abt '[] a -> Docs+        prefixToTerm s e = [ PP.space <> PP.text s <> PP.space+                           , prettyPrec p e+                           ]++-- | Pretty-print @(:$)@ nodes in the AST.+ppSCon :: (ABT Term abt) => Int -> SCon args a -> SArgs abt args -> Docs+ppSCon _ Lam_ = \(e1 :* End) ->+    let (vars, types, body) = ppBinder2 e1 in+    [ PP.text "fn" <+> toDoc vars+                   <+> toDoc types+                    <> PP.colon <> PP.space+    , PP.nest 1 (toDoc body)]++--ppSCon p App_ = \(e1 :* e2 :* End) -> ppArg e1 ++ parens True (ppArg e2)+ppSCon _ App_ = \(e1 :* e2 :* End) -> prettyApps e1 e2++ppSCon _ Let_ = \(e1 :* e2 :* End) ->+    {-+    caseBind e2 $ \x e2' ->+        (ppVariable x <+> PP.equals <+> PP.nest n (pretty e1))+        : pretty e2'+    -}+    let (vars, _, body) = ppBinder2 e2 in+    [toDoc vars <+> PP.equals <+> toDoc (ppArg e1)+    PP.$$ (toDoc body)]+{-+ppSCon p (Ann_ typ) = \(e1 :* End) ->+    [toDoc (ppArg e1) <+> PP.text "::" <+> prettyType p typ]+-}++ppSCon p (PrimOp_     o) = \es          -> ppPrimOp     p o es+ppSCon p (ArrayOp_    o) = \es          -> ppArrayOp    p o es+ppSCon p (CoerceTo_   c) = \(e1 :* End) -> ppCoerceTo   p c e1+ppSCon p (UnsafeFrom_ c) = \(e1 :* End) -> ppUnsafeFrom p c e1+ppSCon p (MeasureOp_  o) = \es          -> ppMeasureOp  p o es+ppSCon _ Dirac = \(e1 :* End) -> [PP.text "return" <+> toDoc (ppArg e1)]+ppSCon _ MBind = \(e1 :* e2 :* End) ->+    let (vars, _, body) = ppBinder2 e2 in+    [toDoc vars <+> PP.text "<~" <+> toDoc (ppArg e1)+        PP.$$ (toDoc body)]++ppSCon p Plate = \(e1 :* e2 :* End) ->+    let (vars, types, body) = ppBinder2 e2 in+    [ PP.text "plate"+      <+> toDoc vars+      <+> PP.text "of"+      <+> (toDoc $ ppArg e1)+      <> PP.colon <> PP.space+    , PP.nest 1 (toDoc body)+    ]++ppSCon p Chain = \(e1 :* e2 :* e3 :* End) ->+    ppFun 11 "chain"+        [ toDoc (ppArg e1)+        , toDoc (ppArg e2) <+> PP.char '$'+        , toDoc $ ppBinder e2+        ]++ppSCon p Integrate = \(e1 :* e2 :* e3 :* End) ->+    let (vars, types, body) = ppBinder2 e3 in+    [ PP.text "integrate"+      <+> toDoc vars+      <+> PP.text "from"+      <+> (toDoc $ ppArg e1)+      <+> PP.text "to"+      <+> (toDoc $ ppArg e2)+      <> PP.colon <> PP.space+    , PP.nest 1 (toDoc body)+    ]++ppSCon p (Summate _ _) = \(e1 :* e2 :* e3 :* End) ->+    let (vars, types, body) = ppBinder2 e3 in+    [ PP.text "summate"+      <+> toDoc vars+      <+> PP.text "from"+      <+> (toDoc $ ppArg e1)+      <+> PP.text "to"+      <+> (toDoc $ ppArg e2)+      <> PP.colon <> PP.space+    , PP.nest 1 (toDoc body)+    ]++ppSCon p (Product _ _) = \(e1 :* e2 :* e3 :* End) ->+    let (vars, types, body) = ppBinder2 e3 in+    [ PP.text "product"+      <+> toDoc vars+      <+> PP.text "from"+      <+> (toDoc $ ppArg e1)+      <+> PP.text "to"+      <+> (toDoc $ ppArg e2)+      <> PP.colon <> PP.space+    , PP.nest 1 (toDoc body)+    ]++ppSCon p Expect = \(e1 :* e2 :* End) ->+    let (vars, types, body) = ppBinder2 e2 in+    [ PP.text "expect"+      <+> toDoc vars+      <+> (toDoc . parens True $ ppArg e1)+      <> PP.colon+    , PP.nest 1 (toDoc body)+    ]++ppSCon p Observe = \(e1 :* e2 :* End) ->+    [ PP.text "observe"+      <+> (toDoc $ ppArg e1)+      <+> (toDoc $ ppArg e2)+    ]+++ppCoerceTo :: ABT Term abt => Int -> Coercion a b -> abt '[] a -> Docs+ppCoerceTo =+    -- BUG: this may not work quite right when the coercion isn't one of the special named ones...+    \p c e -> ppFun p (prettyShow c) [toDoc $ ppArg e]+    where+    prettyShow (CCons (Signed HRing_Real) CNil)           = "prob2real"+    prettyShow (CCons (Signed HRing_Int)  CNil)           = "nat2int"+    prettyShow (CCons (Continuous HContinuous_Real) CNil) = "int2real"+    prettyShow (CCons (Continuous HContinuous_Prob) CNil) = "nat2prob"+    prettyShow (CCons (Continuous HContinuous_Prob)+        (CCons (Signed HRing_Real) CNil))                 = "nat2real"+    prettyShow (CCons (Signed HRing_Int)+        (CCons (Continuous HContinuous_Real) CNil))       = "nat2real"+    prettyShow c = "coerceTo_ " ++ showsPrec 11 c ""+++ppUnsafeFrom :: ABT Term abt => Int -> Coercion a b -> abt '[] b -> Docs+ppUnsafeFrom =+    -- BUG: this may not work quite right when the coercion isn't one of the special named ones...+    \p c e -> ppFun p (prettyShow c) [toDoc $ ppArg e]+    where+    prettyShow (CCons (Signed HRing_Real) CNil) = "real2prob"+    prettyShow (CCons (Signed HRing_Int)  CNil) = "int2nat"+    prettyShow c = "unsafeFrom_ " ++ showsPrec 11 c ""+++-- | Pretty-print a type.+prettyType :: Int -> Sing (a :: Hakaru) -> Doc+prettyType _ SNat         = PP.text "nat"+prettyType _ SInt         = PP.text "int"+prettyType _ SProb        = PP.text "prob"+prettyType _ SReal        = PP.text "real"+prettyType p (SMeasure a) = PP.text "measure" <> PP.parens (prettyType p a)+prettyType p (SArray   a) = PP.text "array" <> PP.parens (prettyType p a)+prettyType p (SFun   a b) = prettyType p a <+> PP.text "->" <+> prettyType p b  +prettyType p typ          =+    case typ of+    SData (STyCon sym `STyApp` a `STyApp` b) _+      | Just Refl <- jmEq1 sym sSymbol_Pair+      -> toDoc $ ppFun p "pair" [prettyType p a, prettyType p b]+      | Just Refl <- jmEq1 sym sSymbol_Either+      -> toDoc $ ppFun p "either" [prettyType p a, prettyType p b]+    SData (STyCon sym `STyApp` a) _+      | Just Refl <- jmEq1 sym sSymbol_Maybe+      -> toDoc $ ppFun p "maybe" [prettyType p a]+    SData (STyCon sym) _+      | Just Refl <- jmEq1 sym sSymbol_Bool+      -> PP.text "bool"+      | Just Refl <- jmEq1 sym sSymbol_Unit+      -> PP.text "unit"+    _ -> PP.text (showsPrec 11 typ "")+++-- | Pretty-print a 'PrimOp' @(:$)@ node in the AST.+ppPrimOp+    :: (ABT Term abt, typs ~ UnLCs args, args ~ LCs typs)+    => Int -> PrimOp typs a -> SArgs abt args -> Docs+ppPrimOp p Not  = \(e1 :* End)       -> ppApply1 p "not" e1+ppPrimOp p Impl = \(e1 :* e2 :* End) ->+    -- TODO: make prettier+    ppFun p "syn"+        [ toDoc $ ppFun 11 "Impl"+            [ toDoc $ ppArg e1+            , toDoc $ ppArg e2+            ]]+ppPrimOp p Diff = \(e1 :* e2 :* End) ->+    -- TODO: make prettier+    ppFun p "syn"+        [ toDoc $ ppFun 11 "Diff"+            [ toDoc $ ppArg e1+            , toDoc $ ppArg e2+            ]]+ppPrimOp p Nand = \(e1 :* e2 :* End) -> ppApply2 p "nand" e1 e2 -- TODO: make infix...+ppPrimOp p Nor  = \(e1 :* e2 :* End) -> ppApply2 p "nor" e1 e2 -- TODO: make infix...+ppPrimOp _ Pi        = \End               -> [PP.text "pi"]+ppPrimOp p Sin       = \(e1 :* End)       -> ppApply1 p "sin"   e1+ppPrimOp p Cos       = \(e1 :* End)       -> ppApply1 p "cos"   e1+ppPrimOp p Tan       = \(e1 :* End)       -> ppApply1 p "tan"   e1+ppPrimOp p Asin      = \(e1 :* End)       -> ppApply1 p "asin"  e1+ppPrimOp p Acos      = \(e1 :* End)       -> ppApply1 p "acos"  e1+ppPrimOp p Atan      = \(e1 :* End)       -> ppApply1 p "atan"  e1+ppPrimOp p Sinh      = \(e1 :* End)       -> ppApply1 p "sinh"  e1+ppPrimOp p Cosh      = \(e1 :* End)       -> ppApply1 p "cosh"  e1+ppPrimOp p Tanh      = \(e1 :* End)       -> ppApply1 p "tanh"  e1+ppPrimOp p Asinh     = \(e1 :* End)       -> ppApply1 p "asinh" e1+ppPrimOp p Acosh     = \(e1 :* End)       -> ppApply1 p "acosh" e1+ppPrimOp p Atanh     = \(e1 :* End)       -> ppApply1 p "atanh" e1+ppPrimOp p RealPow   = \(e1 :* e2 :* End) -> ppBinop "**" 8 RightAssoc p e1 e2+ppPrimOp p Exp       = \(e1 :* End)       -> ppApply1 p "exp"   e1+ppPrimOp p Log       = \(e1 :* End)       -> ppApply1 p "log"   e1+ppPrimOp _ (Infinity _) = \End               -> [PP.text "∞"]+ppPrimOp p GammaFunc    = \(e1 :* End)       -> ppApply1 p "gammaFunc" e1+ppPrimOp p BetaFunc     = \(e1 :* e2 :* End) -> ppApply2 p "betaFunc" e1 e2++ppPrimOp p (Equal   _) = \(e1 :* e2 :* End) -> ppBinop "==" 4 NonAssoc   p e1 e2+ppPrimOp p (Less    _) = \(e1 :* e2 :* End) -> ppBinop "<"  4 NonAssoc   p e1 e2+ppPrimOp p (NatPow  _) = \(e1 :* e2 :* End) -> ppBinop "^"  8 RightAssoc p e1 e2+ppPrimOp p (Negate  _) = \(e1 :* End)       -> ppApply1  p "negate"  e1+ppPrimOp p (Abs     _) = \(e1 :* End)       -> ppApply1  p "abs"     e1+ppPrimOp p (Signum  _) = \(e1 :* End)       -> ppApply1  p "signum"  e1+ppPrimOp p (Recip   _) = \(e1 :* End)       -> ppApply1  p "recip"   e1+ppPrimOp p (NatRoot _) = \(e1 :* e2 :* End) -> ppNatRoot p e1 e2+ppPrimOp p (Erf _)     = \(e1 :* End)       -> ppApply1  p "erf"     e1+++ppNatRoot+    :: (ABT Term abt)+    => Int+    -> abt '[] a+    -> abt '[] 'HNat+    -> Docs+ppNatRoot p e1 e2 =+    caseVarSyn e2 (\x -> ppApply2 p "natroot" e1 e2) $ \t ->+        case t of+          Literal_ (LNat 2) -> ppApply1 p "sqrt"    e1+          _                 -> ppApply2 p "natroot" e1 e2+++-- | Pretty-print a 'ArrayOp' @(:$)@ node in the AST.+ppArrayOp+    :: (ABT Term abt, typs ~ UnLCs args, args ~ LCs typs)+    => Int -> ArrayOp typs a -> SArgs abt args -> Docs+ppArrayOp p (Index   _) = \(e1 :* e2 :* End) ->+    [(toDoc $ parensIf (isArray e1) $ ppArg e1) <>+     PP.text "["        <>+     (toDoc $ ppArg e2) <>+     PP.text "]"]+  where isArray e = caseVarSyn e (const False) $ \t ->+                      case t of+                      Array_ _ _ -> True+                      _          -> False+        parensIf True  e = parens True e+        parensIf False e = e++ppArrayOp p (Size    _) = \(e1 :* End)       -> ppApply1 p "size" e1+ppArrayOp p (Reduce  _) = \(e1 :* e2 :* e3 :* End) ->+    ppFun p "reduce"+        [ toDoc $ ppArg e1 -- N.B., @e1@ uses lambdas rather than being a binding form!+        , toDoc $ ppArg e2+        , toDoc $ ppArg e3+        ]+++-- | Pretty-print a 'MeasureOp' @(:$)@ node in the AST.+ppMeasureOp+    :: (ABT Term abt, typs ~ UnLCs args, args ~ LCs typs)+    => Int -> MeasureOp typs a -> SArgs abt args -> Docs+ppMeasureOp _ Lebesgue    = \End           -> [PP.text "lebesgue"]+ppMeasureOp _ Counting    = \End           -> [PP.text "counting"]+ppMeasureOp p Categorical = \(e1 :* End)   -> ppApply1 p "categorical" e1+ppMeasureOp p Uniform = \(e1 :* e2 :* End) -> ppApply2 p "uniform"     e1 e2+ppMeasureOp p Normal  = \(e1 :* e2 :* End) -> ppApply2 p "normal"      e1 e2+ppMeasureOp p Poisson = \(e1 :* End)       -> ppApply1 p "poisson"     e1+ppMeasureOp p Gamma   = \(e1 :* e2 :* End) -> ppApply2 p "gamma"       e1 e2+ppMeasureOp p Beta    = \(e1 :* e2 :* End) -> ppApply2 p "beta"        e1 e2++-- BUG: doubles may not properly and unambiguously represent the correct rational! Consider using 'ppRatio' instead.+instance Pretty Literal where+    prettyPrec_ _ (LNat  n) = [PP.integer (fromNatural n)]+    prettyPrec_ _ (LInt  i) = [PP.integer i]+    prettyPrec_ p (LProb l) =+        [ppRatio p $ fromNonNegativeRational l]+    prettyPrec_ p (LReal r) = [ppRatio p r]++instance Pretty Value where+    prettyPrec_ _ (VNat  n)    = [PP.int (fromNat n)]+    prettyPrec_ _ (VInt  i)    = [PP.int i]+    prettyPrec_ _ (VProb l)    =+        [PP.double $ LF.fromLogFloat l]+    prettyPrec_ _ (VReal r)    = [PP.double r]+    prettyPrec_ p (VDatum d)   = prettyPrec_ p d+    prettyPrec_ _ (VLam _)     = [PP.text "<function>"]+    prettyPrec_ _ (VMeasure _) = [PP.text "<measure>"]+    prettyPrec_ p (VArray a)   =+        ppList . V.toList $ V.map (toDoc . prettyPrec_ p) a++prettyValue :: Value a -> Doc+prettyValue = toDoc . prettyPrec_ 0++instance Pretty f => Pretty (Datum f) where+    prettyPrec_ p (Datum hint _typ d)+        | Text.null hint =+            ppFun p "datum_"+                [error "TODO: prettyPrec_@Datum"]+        | otherwise =+            case Text.unpack hint of+            -- Special cases for certain datums+            "pair"  -> ppFun p ""+                (foldMap11 ((:[]) . toDoc . prettyPrec_ 11) d) +            "true"  -> [PP.text "true"]+            "false" -> [PP.text "false"]+            "unit"  -> [PP.text "()"]+            -- General case+            _       -> ppFun p (Text.unpack hint)+                (foldMap11 ((:[]) . toDoc . prettyPrec_ 11) d)+                ++ [PP.text "." <+> prettyType p _typ]+++-- HACK: need to pull this out in order to get polymorphic recursion over @xs@+ppPattern :: Int -> [Doc] -> Pattern xs a -> (Docs, [Doc])+ppPattern _ _      PWild = ([PP.text "_"], [])+ppPattern _ (v:vs) PVar  = ([v], vs)+ppPattern p vars   (PDatum hint d0)+    | Text.null hint = error "TODO: prettyPrec_@Pattern"+    | otherwise      =+        case Text.unpack hint of+        -- Special cases for certain pDatums+        "true"  -> ([PP.text "true"],  vars)+        "false" -> ([PP.text "false"], vars)+        "pair"  -> ppFunWithVars p Text.empty+        -- General case+        _        -> ppFunWithVars p hint+    where+    ppFunWithVars p hint = (ppFun p (Text.unpack hint) g, vars')+       where (g, vars') = goCode d0 vars++    goCode :: PDatumCode xss vars a -> [Doc] -> (Docs, [Doc])+    goCode (PInr d) = goCode   d+    goCode (PInl d) = goStruct d++    goStruct :: PDatumStruct xs vars a -> [Doc] -> (Docs, [Doc])+    goStruct PDone       vars  = ([], vars)+    goStruct (PEt d1 d2) vars = (gF ++ gS, vars'')+       where (gF, vars')  = goFun d1 vars+             (gS, vars'') = goStruct d2 vars' ++    goFun :: PDatumFun x vars a -> [Doc] -> (Docs, [Doc])+    goFun (PKonst d) vars = ([toDoc $ fst r], snd r)+       where r = ppPattern 11 vars d+    goFun (PIdent d) vars = ([toDoc $ fst r], snd r)+       where r = ppPattern 11 vars d+++instance (ABT Term abt) => Pretty (Branch a abt) where+    -- BUG: we can't actually use the HOAS API here, since we+    --      aren't using a Prelude-defined @branch@...+    -- HACK: don't *always* print parens; pass down the precedence to+    --       'ppBinder' to have them decide if they need to or not.+    prettyPrec_ p (Branch pat e) =+        let (vars, _, body) = ppBinder2 e in+        [ (toDoc . fst $ ppPattern 11 vars pat) <> PP.colon <> PP.space+        , PP.nest 1 $ toDoc $ body+        ]++----------------------------------------------------------------+type DList a = [a] -> [a]++prettyApps :: (ABT Term abt) => abt '[] (a ':-> b) -> abt '[] a -> Docs+prettyApps = \ e1 e2 ->+    case reduceLams e1 e2 of+    Just e2' -> ppArg e2'+    Nothing  ->+      let (d, vars) = collectApps e1 (pretty e2 :) in+      [d <> ppTuple (vars [])]+    where+    reduceLams+        :: (ABT Term abt)+        => abt '[] (a ':-> b) -> abt '[] a -> Maybe (abt '[] b)+    reduceLams e1 e2 =+        caseVarSyn e1 (const Nothing) $ \t ->+            case t of+            Lam_ :$ e1 :* End ->+              caseBind e1 $ \x e1' ->+                Just (subst x e2 e1')+            _                 -> Nothing++    collectApps+        :: (ABT Term abt)+        => abt '[] (a ':-> b) -> DList Doc -> (Doc, DList Doc)+    collectApps e es = +        caseVarSyn e (\x -> (ppVariable x, es)) $ \t ->+            case t of+            App_ :$ e1 :* e2 :* End -> collectApps e1 ((pretty e2 :) . es)+            _                       -> (pretty e, es)+++prettyLams :: (ABT Term abt) => abt '[a] b -> Doc+prettyLams = \e ->+    let (d, vars) = collectLams e id in+    PP.char '\\' <+> PP.sep (vars []) <+> PP.text "->" <+> d+    where+    collectLams+        :: (ABT Term abt)+        => abt '[a] b -> DList Doc -> (Doc, DList Doc)+    collectLams e xs = +        caseBind e $ \x e' ->+            let xs' = xs . (ppVariable x :) in+            caseVarSyn e' (\y -> (ppVariable y, xs')) $ \t ->+                case t of+                Lam_ :$ e1 :* End -> collectLams e1 xs'+                _                 -> (pretty e', xs')+++-- | For the \"@lam $ \x ->\n@\"  style layout.+adjustHead :: (Doc -> Doc) -> Docs -> Docs+adjustHead f []     = [f (toDoc [])]+adjustHead f (d:ds) = f d : ds++parens :: Bool -> Docs -> Docs+parens True  ds = [PP.parens (PP.nest 1 (toDoc ds))]+parens False ds = [PP.parens (toDoc ds)]++ppList :: [Doc] -> Docs+ppList = (:[]) . PP.brackets . PP.nest 1 . PP.fsep . PP.punctuate PP.comma++ppTuple :: [Doc] -> Doc+ppTuple = PP.parens . PP.sep . PP.punctuate PP.comma++-- TODO: why does this take the precedence argument if it doesn't care?+ppFun :: Int -> String -> [Doc] -> Docs+ppFun _ f [] = [PP.text f <> PP.text "()"]+ppFun _ f ds = [PP.text f <> ppTuple ds]++ppArg :: (ABT Term abt) => abt '[] a -> Docs+ppArg = prettyPrec_ 11 . LC_++ppApply1 :: (ABT Term abt) => Int -> String -> abt '[] a -> Docs+ppApply1 p f e1 = ppFun p f [toDoc $ ppArg e1]++ppApply2+    :: (ABT Term abt) => Int -> String -> abt '[] a -> abt '[] b -> Docs+ppApply2 p f e1 e2 = ppFun p f [toDoc $ ppArg e1, toDoc $ ppArg e2]++ppBinop+    :: (ABT Term abt)+    => String -> Int -> Associativity+    -> Int -> abt '[] a -> abt '[] b -> Docs+ppBinop op p0 assoc =+    let (p1,p2) =+            case assoc of+            LeftAssoc  -> (p0, 1 + p0)+            RightAssoc -> (1 + p0, p0)+            NonAssoc   -> (1 + p0, 1 + p0)+    in \p e1 e2 ->+        parens (p > p0)+            [ prettyPrec p1 e1+            , PP.space <> PP.text op <> PP.space+            , prettyPrec p2 e2+            ]++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Pretty/Haskell.hs view
@@ -0,0 +1,523 @@+{-# LANGUAGE GADTs+           , KindSignatures+           , DataKinds+           , FlexibleContexts+           , UndecidableInstances+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.02.21+-- |+-- Module      :  Language.Hakaru.Pretty.Haskell+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+--+----------------------------------------------------------------+module Language.Hakaru.Pretty.Haskell+    (+    -- * The user-facing API+      pretty+    , prettyPrec+    , prettyAssoc+    , prettyPrecAssoc++    -- * Helper functions (semi-public internal API)+    , ppVariable+    , ppVariables+    , ppBinder+    , ppCoerceTo+    , ppUnsafeFrom+    , ppRatio+    , Associativity(..)+    , ppBinop+    , Pretty(..)+    ) where+import           Data.Ratio+import           Text.PrettyPrint (Doc, (<>), (<+>))+import qualified Text.PrettyPrint   as PP+import qualified Data.Foldable      as F+import qualified Data.List.NonEmpty as L+import qualified Data.Text          as Text+import qualified Data.Sequence      as Seq -- Because older versions of "Data.Foldable" do not export 'null' apparently...++import Data.Number.Nat                 (fromNat)+import Data.Number.Natural             (fromNatural)+import Language.Hakaru.Syntax.IClasses (fmap11, foldMap11, List1(..))+import Language.Hakaru.Types.DataKind+import Language.Hakaru.Types.Coercion+import Language.Hakaru.Types.HClasses+import Language.Hakaru.Syntax.AST+import Language.Hakaru.Syntax.Datum+import Language.Hakaru.Syntax.ABT+----------------------------------------------------------------++-- | Pretty-print a term.+pretty :: (ABT Term abt) => abt '[] a -> Doc+pretty = prettyPrec 0+++-- | Pretty-print a term at a given precendence level.+prettyPrec :: (ABT Term abt) => Int -> abt '[] a -> Doc+prettyPrec p = toDoc . prettyPrec_ p . LC_+++-- | Pretty-print a variable\/term association pair.+prettyAssoc :: (ABT Term abt) => Assoc (abt '[]) -> Doc+prettyAssoc = prettyPrecAssoc 0+++-- | Pretty-print an association at a given precendence level.+prettyPrecAssoc :: (ABT Term abt) => Int -> Assoc (abt '[]) -> Doc+prettyPrecAssoc p (Assoc x e) =+    toDoc $ ppFun p "Assoc"+        [ ppVariable x+        , prettyPrec 11 e+        ]++----------------------------------------------------------------+class Pretty (f :: Hakaru -> *) where+    -- | A polymorphic variant if 'prettyPrec', for internal use.+    prettyPrec_ :: Int -> f a -> Docs++type Docs = [Doc] ++-- So far as I can tell from the documentation, if the input is a singleton list then the result is the same as that singleton.+toDoc :: Docs -> Doc+toDoc = PP.sep+++-- | Pretty-print a variable.+ppVariable :: Variable (a :: Hakaru) -> Doc+ppVariable x = hint <> (PP.int . fromNat . varID) x+    where+    hint+        | Text.null (varHint x) = PP.char 'x' -- We used to use '_' but...+        | otherwise             = (PP.text . Text.unpack . varHint) x++-- | Pretty-print a list of variables as a list of variables. N.B., the output is not valid Haskell code since it uses the special built-in list syntax rather than using the 'List1' constructors...+ppVariables :: List1 Variable (xs :: [Hakaru]) -> Docs+ppVariables = ppList . go+    where+    go :: List1 Variable (xs :: [Hakaru]) -> Docs+    go Nil1         = []+    go (Cons1 x xs) = ppVariable x : go xs+++-- | Pretty-print Hakaru binders as a Haskell lambda, as per our HOAS API.+ppBinder :: (ABT Term abt) => abt xs a -> Docs+ppBinder e =+    case go [] (viewABT e) of+    ([],  body) -> body+    (vars,body) -> PP.char '\\' <+> PP.sep vars <+> PP.text "->" : body+    where+    go :: (ABT Term abt) => [Doc] -> View (Term abt) xs a -> ([Doc],Docs)+    go xs (Syn  t)   = (reverse xs, prettyPrec_ 0 (LC_ (syn t)))+    go xs (Var  x)   = (reverse xs, [ppVariable x])+    go xs (Bind x v) =+        -- HACK: how can we avoid calling 'unviewABT' here?+        let x' = if True -- x `memberVarSet` freeVars (unviewABT v)+                 then ppVariable x+                 else PP.char '_'+        in go (x' : xs) v+++-- TODO: since switching to ABT2, this instance requires -XFlexibleContexts; we should fix that if we can+-- BUG: since switching to ABT2, this instance requires -XUndecidableInstances; must be fixed!+instance (ABT Term abt) => Pretty (LC_ abt) where+  prettyPrec_ p (LC_ e) =+    caseVarSyn e ((:[]) . ppVariable) $ \t -> +        case t of+        o :$ es      -> ppSCon p o es+        NaryOp_ o es ->+            -- TODO: make sure these ops actually have those precedences in the Prelude!!+            let prettyNaryOp :: NaryOp a -> (String, Int, Maybe String)+                prettyNaryOp And  = ("&&", 3, Just "true")+                prettyNaryOp Or   = ("||", 2, Just "false")+                prettyNaryOp Xor  = ("`xor`", 0, Just "false")+                -- BUG: even though 'Iff' is associative (in Boolean algebras), we should not support n-ary uses in our *surface* syntax. Because it's too easy for folks to confuse "a <=> b <=> c" with "(a <=> b) /\ (b <=> c)".+                prettyNaryOp Iff      = ("`iff`", 0, Just "true")+                prettyNaryOp (Min  _) = ("`min`", 5, Nothing)+                prettyNaryOp (Max  _) = ("`max`", 5, Nothing)+                -- TODO: pretty print @(+ negate)@ as @(-)@ and @(* recip)@ as @(/)@+                prettyNaryOp (Sum  _) = ("+",     6, Just "zero")+                prettyNaryOp (Prod _) = ("*",     7, Just "one")+            in+            let (opName,opPrec,maybeIdentity) = prettyNaryOp o in+            if Seq.null es+            then+                case maybeIdentity of+                Just identity -> [PP.text identity]+                Nothing ->+                    ppFun p "syn"+                        [ toDoc $ ppFun 11 "NaryOp_"+                            [ PP.text (showsPrec 11 o "")+                            , PP.text "(Seq.fromList [])"+                            ]]+            else+                parens (p > opPrec)+                    . PP.punctuate (PP.space <> PP.text opName)+                    . map (prettyPrec opPrec)+                    $ F.toList es++        Literal_ v    -> prettyPrec_ p v+        Empty_   _    -> [PP.text "empty"]+        Array_ e1 e2  ->+            ppFun 11 "array"+                [ ppArg e1 <+> PP.char '$'+                , toDoc $ ppBinder e2+                ]+        Datum_ d      -> prettyPrec_ p (fmap11 LC_ d)+        Case_  e1 bs  ->+            -- TODO: should we also add hints to the 'Case_' constructor to know whether it came from 'if_', 'unpair', etc?+             ppFun p "case_"+                 [ ppArg e1+                 , toDoc $ ppList (map (toDoc . prettyPrec_ 0) bs)+                 ]+        Superpose_ pes ->+            case pes of+            (e1,e2) L.:| [] ->+                -- Or we could print it as @weight e1 *> e2@ excepting that has an extra redex in it compared to the AST itself.+                ppFun 11 "pose"+                    [ ppArg e1 <+> PP.char '$'+                    , ppArg e2+                    ]+            _ ->+                ppFun p "superpose"+                    [ toDoc+                    . ppList+                    . map (\(e1,e2) -> ppTuple [pretty e1, pretty e2])+                    $ L.toList pes+                    ]++        Reject_ _ -> [PP.text "reject"]++-- | Pretty-print @(:$)@ nodes in the AST.+ppSCon :: (ABT Term abt) => Int -> SCon args a -> SArgs abt args -> Docs+ppSCon p Lam_ = \(e1 :* End) ->+    parens (p > 0) $ adjustHead (PP.text "lam $" <+>) (ppBinder e1)+ppSCon p App_ = \(e1 :* e2 :* End) -> ppBinop "`app`" 9 LeftAssoc p e1 e2 -- BUG: this puts extraneous parentheses around e2 when it's a function application...+ppSCon p Let_ = \(e1 :* e2 :* End) ->+    parens (p > 0) $ +        adjustHead+            (PP.text "let_" <+> ppArg e1 <+> PP.char '$' <+>)+            (ppBinder e2)+{-+ppSCon p (Ann_ typ) = \(e1 :* End) ->+    ppFun p "ann_"+        [ PP.text (showsPrec 11 typ "") -- TODO: make this prettier. Add hints to the singletons?+        , ppArg e1+        ]+-}+ppSCon p (PrimOp_     o) = \es          -> ppPrimOp     p o es+ppSCon p (ArrayOp_    o) = \es          -> ppArrayOp    p o es+ppSCon p (CoerceTo_   c) = \(e1 :* End) -> ppCoerceTo   p c e1+ppSCon p (UnsafeFrom_ c) = \(e1 :* End) -> ppUnsafeFrom p c e1+ppSCon p (MeasureOp_  o) = \es          -> ppMeasureOp  p o es+ppSCon p Dirac           = \(e1 :* End) -> ppApply1 p "dirac" e1+ppSCon p MBind = \(e1 :* e2 :* End) ->+    parens (p > 1) $+        adjustHead+            (prettyPrec 1 e1 <+> PP.text ">>=" <+>)+            (ppBinder e2)+ppSCon p Expect = \(e1 :* e2 :* End) ->+    -- N.B., for this to be read back in correctly, "Language.Hakaru.Expect" must be in scope as well as the prelude.+    parens (p > 0) $+        adjustHead+            (PP.text "expect" <+> ppArg e1 <+> PP.char '$' <+>)+            (ppBinder e2)+ppSCon p Observe   = \(e1 :* e2 :* End) -> ppApply2 p "observe" e1 e2+ppSCon p Integrate = \(e1 :* e2 :* e3 :* End) ->+    ppFun p "integrate"+        [ ppArg e1+        , ppArg e2+        , toDoc $ parens True (ppBinder e3)+        ]+ppSCon p (Summate _ _) = \(e1 :* e2 :* e3 :* End) ->+    ppFun p "summate"+        [ ppArg e1+        , ppArg e2+        , toDoc $ parens True (ppBinder e3)+        ]++ppSCon p (Product _ _) = \(e1 :* e2 :* e3 :* End) ->+    ppFun p "product"+        [ ppArg e1+        , ppArg e2+        , toDoc $ parens True (ppBinder e3)+        ]++ppSCon _ Plate = \(e1 :* e2 :* End) -> +    ppFun 11 "plate"+        [ ppArg e1 <+> PP.char '$'+        , toDoc $ ppBinder e2+        ]++ppSCon _ Chain = \(e1 :* e2 :* e3 :* End) ->+    ppFun 11 "chain"+        [ ppArg e1+        , ppArg e2 <+> PP.char '$'+        , toDoc $ ppBinder e3+        ]++ppCoerceTo :: ABT Term abt => Int -> Coercion a b -> abt '[] a -> Docs+ppCoerceTo =+    -- BUG: this may not work quite right when the coercion isn't one of the special named ones...+    \p c e -> ppFun p (prettyShow c) [ppArg e]+    where+    prettyShow (CCons (Signed HRing_Real) CNil)           = "fromProb"+    prettyShow (CCons (Signed HRing_Int)  CNil)           = "nat2int"+    prettyShow (CCons (Continuous HContinuous_Real) CNil) = "fromInt"+    prettyShow (CCons (Continuous HContinuous_Prob) CNil) = "nat2prob"+    prettyShow (CCons (Continuous HContinuous_Prob)+        (CCons (Signed HRing_Real) CNil))                 = "nat2real"+    prettyShow (CCons (Signed HRing_Int)+        (CCons (Continuous HContinuous_Real) CNil))       = "nat2real"+    prettyShow c = "coerceTo_ " ++ showsPrec 11 c ""+++ppUnsafeFrom :: ABT Term abt => Int -> Coercion a b -> abt '[] b -> Docs+ppUnsafeFrom =+    -- BUG: this may not work quite right when the coercion isn't one of the special named ones...+    \p c e -> ppFun p (prettyShow c) [ppArg e]+    where+    prettyShow (CCons (Signed HRing_Real) CNil) = "unsafeProb"+    prettyShow (CCons (Signed HRing_Int)  CNil) = "unsafeNat"+    prettyShow c = "unsafeFrom_ " ++ showsPrec 11 c ""+++-- | Pretty-print a 'PrimOp' @(:$)@ node in the AST.+ppPrimOp+    :: (ABT Term abt, typs ~ UnLCs args, args ~ LCs typs)+    => Int -> PrimOp typs a -> SArgs abt args -> Docs+ppPrimOp p Not  = \(e1 :* End)       -> ppApply1 p "not" e1+ppPrimOp p Impl = \(e1 :* e2 :* End) ->+    -- TODO: make prettier+    ppFun p "syn"+        [ toDoc $ ppFun 11 "Impl"+            [ ppArg e1+            , ppArg e2+            ]]+ppPrimOp p Diff = \(e1 :* e2 :* End) ->+    -- TODO: make prettier+    ppFun p "syn"+        [ toDoc $ ppFun 11 "Diff"+            [ ppArg e1+            , ppArg e2+            ]]+ppPrimOp p Nand = \(e1 :* e2 :* End)        -> ppApply2 p "nand" e1 e2 -- TODO: make infix...+ppPrimOp p Nor  = \(e1 :* e2 :* End)        -> ppApply2 p "nor" e1 e2 -- TODO: make infix...+ppPrimOp _ Pi        = \End                 -> [PP.text "pi"]+ppPrimOp p Sin       = \(e1 :* End)         -> ppApply1 p "sin"   e1+ppPrimOp p Cos       = \(e1 :* End)         -> ppApply1 p "cos"   e1+ppPrimOp p Tan       = \(e1 :* End)         -> ppApply1 p "tan"   e1+ppPrimOp p Asin      = \(e1 :* End)         -> ppApply1 p "asin"  e1+ppPrimOp p Acos      = \(e1 :* End)         -> ppApply1 p "acos"  e1+ppPrimOp p Atan      = \(e1 :* End)         -> ppApply1 p "atan"  e1+ppPrimOp p Sinh      = \(e1 :* End)         -> ppApply1 p "sinh"  e1+ppPrimOp p Cosh      = \(e1 :* End)         -> ppApply1 p "cosh"  e1+ppPrimOp p Tanh      = \(e1 :* End)         -> ppApply1 p "tanh"  e1+ppPrimOp p Asinh     = \(e1 :* End)         -> ppApply1 p "asinh" e1+ppPrimOp p Acosh     = \(e1 :* End)         -> ppApply1 p "acosh" e1+ppPrimOp p Atanh     = \(e1 :* End)         -> ppApply1 p "atanh" e1+ppPrimOp p RealPow   = \(e1 :* e2 :* End)   -> ppBinop "**" 8 RightAssoc p e1 e2+ppPrimOp p Exp       = \(e1 :* End)         -> ppApply1 p "exp"   e1+ppPrimOp p Log       = \(e1 :* End)         -> ppApply1 p "log"   e1+ppPrimOp _ (Infinity _)     = \End          -> [PP.text "infinity"]+ppPrimOp p GammaFunc = \(e1 :* End)         -> ppApply1 p "gammaFunc" e1+ppPrimOp p BetaFunc  = \(e1 :* e2 :* End)   -> ppApply2 p "betaFunc" e1 e2+ppPrimOp p (Equal   _) = \(e1 :* e2 :* End) -> ppBinop "==" 4 NonAssoc   p e1 e2+ppPrimOp p (Less    _) = \(e1 :* e2 :* End) -> ppBinop "<"  4 NonAssoc   p e1 e2+ppPrimOp p (NatPow  _) = \(e1 :* e2 :* End) -> ppBinop "^"  8 RightAssoc p e1 e2+ppPrimOp p (Negate  _) = \(e1 :* End)       -> ppApply1 p "negate" e1+ppPrimOp p (Abs     _) = \(e1 :* End)       -> ppApply1 p "abs_"   e1+ppPrimOp p (Signum  _) = \(e1 :* End)       -> ppApply1 p "signum" e1+ppPrimOp p (Recip   _) = \(e1 :* End)       -> ppApply1 p "recip"  e1+ppPrimOp p (NatRoot _) = \(e1 :* e2 :* End) ->+    -- N.B., argument order is swapped!+    ppBinop "`thRootOf`" 9 LeftAssoc p e2 e1+ppPrimOp p (Erf _) = \(e1 :* End)           -> ppApply1 p "erf" e1+++-- | Pretty-print a 'ArrayOp' @(:$)@ node in the AST.+ppArrayOp+    :: (ABT Term abt, typs ~ UnLCs args, args ~ LCs typs)+    => Int -> ArrayOp typs a -> SArgs abt args -> Docs+ppArrayOp p (Index   _) = \(e1 :* e2 :* End) ->+    ppBinop "!" 9 LeftAssoc p e1 e2+ppArrayOp p (Size    _) = \(e1 :* End) ->+    ppApply1 p "size" e1+ppArrayOp p (Reduce  _) = \(e1 :* e2 :* e3 :* End) ->+    ppFun p "reduce"+        [ ppArg e1 -- N.B., @e1@ uses lambdas rather than being a binding form!+        , ppArg e2+        , ppArg e3+        ]+++-- | Pretty-print a 'MeasureOp' @(:$)@ node in the AST.+ppMeasureOp+    :: (ABT Term abt, typs ~ UnLCs args, args ~ LCs typs)+    => Int -> MeasureOp typs a -> SArgs abt args -> Docs+ppMeasureOp _ Lebesgue    = \End           -> [PP.text "lebesgue"]+ppMeasureOp _ Counting    = \End           -> [PP.text "counting"]+ppMeasureOp p Categorical = \(e1 :* End)   -> ppApply1 p "categorical" e1+ppMeasureOp p Uniform = \(e1 :* e2 :* End) -> ppApply2 p "uniform"     e1 e2+ppMeasureOp p Normal  = \(e1 :* e2 :* End) -> ppApply2 p "normal"      e1 e2+ppMeasureOp p Poisson = \(e1 :* End)       -> ppApply1 p "poisson"     e1+ppMeasureOp p Gamma   = \(e1 :* e2 :* End) -> ppApply2 p "gamma"       e1 e2+ppMeasureOp p Beta    = \(e1 :* e2 :* End) -> ppApply2 p "beta"        e1 e2++instance Pretty Literal where+    prettyPrec_ p (LNat  n) = ppFun p "nat_"  [PP.integer (fromNatural n)]+    prettyPrec_ p (LInt  i) = ppFun p "int_"  [PP.integer i]+    prettyPrec_ p (LProb l) = ppFun p "prob_" [ppRatio 11 l]+    prettyPrec_ p (LReal r) = ppFun p "real_" [ppRatio 11 r]+++instance Pretty f => Pretty (Datum f) where+    prettyPrec_ p (Datum hint _typ d)+        | Text.null hint =+            ppFun p "datum_"+                [error "TODO: prettyPrec_@Datum"]+        | otherwise = +          ppFun p "ann_"+            [ PP.parens . PP.text . show $ _typ+            , PP.parens . toDoc $ ppFun p (Text.unpack hint)+                (foldMap11 ((:[]) . toDoc . prettyPrec_ 11) d)+            ]++-- HACK: need to pull this out in order to get polymorphic recursion over @xs@+ppPattern :: Int -> Pattern xs a -> Docs+ppPattern _ PWild = [PP.text "PWild"]+ppPattern _ PVar  = [PP.text "PVar"]+ppPattern p (PDatum hint d0)+    | Text.null hint = error "TODO: prettyPrec_@Pattern"+    | otherwise      = ppFun p ("p" ++ Text.unpack hint) (goCode d0)+    where+    goCode :: PDatumCode xss vars a -> Docs+    goCode (PInr d) = goCode   d+    goCode (PInl d) = goStruct d++    goStruct :: PDatumStruct xs vars a -> Docs+    goStruct PDone       = []+    goStruct (PEt d1 d2) = goFun d1 ++ goStruct d2++    goFun :: PDatumFun x vars a -> Docs+    goFun (PKonst d) = [toDoc $ ppPattern 11 d]+    goFun (PIdent d) = [toDoc $ ppPattern 11 d]+++instance Pretty (Pattern xs) where+    prettyPrec_ = ppPattern+++instance (ABT Term abt) => Pretty (Branch a abt) where+    prettyPrec_ p (Branch pat e) =+        ppFun p "branch"+            [ toDoc $ prettyPrec_ 11 pat+            , PP.parens . toDoc $ ppBinder e+            -- BUG: we can't actually use the HOAS API here, since we aren't using a Prelude-defined @branch@...+            -- HACK: don't *always* print parens; pass down the precedence to 'ppBinder' to+            --       have them decide if they need to or not.+            ]++----------------------------------------------------------------+-- | For the \"@lam $ \x ->\n@\"  style layout.+adjustHead :: (Doc -> Doc) -> Docs -> Docs+adjustHead f []     = [f (toDoc [])]+adjustHead f (d:ds) = f d : ds++{- -- unused+-- | For the \"@lam (\x ->\n\t...)@\"  style layout.+nestTail :: Int -> Docs -> Docs+nestTail _ []     = []+nestTail n (d:ds) = [d, PP.nest n (toDoc ds)]+-}++parens :: Bool -> Docs -> Docs+parens True  ds = [PP.parens (PP.nest 1 (toDoc ds))]+parens False ds = ds++ppList :: [Doc] -> Docs+ppList = (:[]) . PP.brackets . PP.nest 1 . PP.fsep . PP.punctuate PP.comma++ppTuple :: [Doc] -> Doc+ppTuple = PP.parens . PP.sep . PP.punctuate PP.comma++ppFun :: Int -> String -> [Doc] -> Docs+ppFun _ f [] = [PP.text f]+ppFun p f ds =+    parens (p > 9) [PP.text f <+> PP.nest (1 + length f) (PP.sep ds)]++ppArg :: (ABT Term abt) => abt '[] a -> Doc+ppArg = prettyPrec 11++ppApply1 :: (ABT Term abt) => Int -> String -> abt '[] a -> Docs+ppApply1 p f e1 = ppFun p f [ppArg e1]++ppApply2+    :: (ABT Term abt) => Int -> String -> abt '[] a -> abt '[] b -> Docs+ppApply2 p f e1 e2 = ppFun p f [ppArg e1, ppArg e2]+++-- | Something prettier than 'PP.rational'. This works correctly+-- for both 'Rational' and 'NonNegativeRational', though it may not+-- work for other @a@ types.+--+-- N.B., the resulting string assumes prefix negation and the+-- 'Fractional' @(/)@ operator are both in scope.+ppRatio :: (Show a, Integral a) => Int -> Ratio a -> Doc+ppRatio p r+    | d == 1    = ppShowS $ showsPrec p n+    | n < 0     =+        ppShowS+        . showParen (p > 7)+            $ showChar '-' -- TODO: is this guaranteed valid no matter @a@?+            . showsPrec 8 (negate n)+            . showChar '/'+            . showsPrec 8 d+    | otherwise =+        ppShowS+        . showParen (p > 7)+            $ showsPrec 8 n+            . showChar '/'+            . showsPrec 8 d+    where+    d = denominator r+    n = numerator   r++    ppShowS s = PP.text (s [])++    {-+    -- TODO: we might prefer to use something like:+    PP.cat [ppIntegral n, PP.char '/' <> ppIntegral d ]+    where ppIntegral = PP.text . show+    -}+++data Associativity = LeftAssoc | RightAssoc | NonAssoc++ppBinop+    :: (ABT Term abt)+    => String -> Int -> Associativity+    -> Int -> abt '[] a -> abt '[] b -> Docs+ppBinop op p0 assoc =+    let (p1,p2) =+            case assoc of+            LeftAssoc  -> (p0, 1 + p0)+            RightAssoc -> (1 + p0, p0)+            NonAssoc   -> (1 + p0, 1 + p0)+    in \p e1 e2 -> +        parens (p > p0)+            [ prettyPrec p1 e1+            , PP.text op+                <+> prettyPrec p2 e2+            ]++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Pretty/Maple.hs view
@@ -0,0 +1,382 @@+{-# LANGUAGE MultiParamTypeClasses+           , OverloadedStrings+           , FlexibleInstances+           , FlexibleContexts+           , ScopedTypeVariables+           , CPP+           , GADTs+           , TypeFamilies+           , DataKinds+           , TypeOperators+           #-}+++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.04.28+-- |+-- Module      :  Language.Hakaru.Pretty.Maple+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- TODO: given as the constructed strings will just be printed,+-- it'd reduce memory pressure a lot to replace our use of 'ShowS'+-- with a similar builder type for 'Text.Text' (or, if the character+-- encoding is fixed\/known, a builder type for @ByteString@).+----------------------------------------------------------------+module Language.Hakaru.Pretty.Maple (pretty, mapleType) where++import qualified Data.Text           as Text+import           Data.Ratio+import           Data.Number.Nat     (fromNat)+import           Data.Sequence       (Seq)+import qualified Data.Foldable       as F+import qualified Data.List.NonEmpty  as L+import           Control.Monad.State (MonadState(..), State, runState)+import           Data.Maybe          (isJust)++#if __GLASGOW_HASKELL__ < 710+import           Control.Applicative   (Applicative(..), (<$>))+#endif++import Language.Hakaru.Types.DataKind+import Language.Hakaru.Types.Sing+import Language.Hakaru.Syntax.AST+import Language.Hakaru.Syntax.Datum+import Language.Hakaru.Syntax.ABT+import Language.Hakaru.Syntax.IClasses+import Language.Hakaru.Expect+----------------------------------------------------------------++pretty :: (ABT Term abt) => abt '[] a -> String+pretty = ($[]) . mapleAST . LC_++app1 :: (ABT Term abt) => String -> abt '[] a -> ShowS+app1 fn x = op1 fn (arg x)+{-# INLINE app1 #-}++app2 :: (ABT Term abt) => String -> abt '[] a -> abt '[] b -> ShowS+app2 fn x y = op2 fn (arg x) (arg y)+{-# INLINE app2 #-}++app3 :: (ABT Term abt)+    => String -> abt '[] a -> abt '[] b -> abt '[] c -> ShowS+app3 fn x y z = op3 fn (arg x) (arg y) (arg z)+{-# INLINE app3 #-}++-- HACK: why doesn't Foldable imply Functor anymore?+appN :: (ABT Term abt, Functor f, F.Foldable f)+    => String -> f (abt '[] a) -> ShowS+appN fn xs = opN fn (arg <$> xs)+{-# INLINE appN #-}++op1 ::  String -> ShowS -> ShowS+op1 fn x = showString fn . parens x+{-# INLINE op1 #-}++op2 :: String -> ShowS -> ShowS -> ShowS+op2 fn x y = showString fn . parens (x . showString ", " . y)+{-# INLINE op2 #-}++op3 :: String -> ShowS -> ShowS -> ShowS -> ShowS+op3 fn x y z+    = showString fn+    . parens+        ( x+        . showString ", "+        . y+        . showString ", "+        . z+        )+{-# INLINE op3 #-}++opN :: F.Foldable f => String -> f ShowS -> ShowS+opN fn xs = showString fn . parens (commaSep xs)+{-# INLINE opN #-}++meq :: (ABT Term abt) => abt '[] a -> abt '[] b -> ShowS+meq x y = arg x . showChar '=' . parens (arg y)+{-# INLINE meq #-}++parens :: ShowS -> ShowS+parens a = showChar '(' . a . showChar ')'+{-# INLINE parens #-}++intercalate :: F.Foldable f => ShowS -> f ShowS -> ShowS+intercalate sep = F.foldr1 (\a b -> a . sep . b)+{-# INLINE intercalate #-}++commaSep :: F.Foldable f => f ShowS -> ShowS+commaSep = intercalate (showString ", ")+{-# INLINE commaSep #-}++mapleAST :: (ABT Term abt) => LC_ abt a -> ShowS+mapleAST (LC_ e) =+    caseVarSyn e var1 $ \t ->+        case t of+        o :$ es        -> mapleSCon o  es+        NaryOp_ op es  -> mapleNary op es+        Literal_ v     -> mapleLiteral v+        Empty_ _       -> error "TODO: mapleAST{Empty}"+        Array_ e1 e2   -> +            caseBind e2 $ \x e2' ->+                app3 "ary" e1 (var x) e2'+        Datum_ (Datum "true"  _typ (Inl Done)      ) -> showString "true"+        Datum_ (Datum "false" _typ (Inr (Inl Done))) -> showString "false"+        Datum_ d       -> mapleDatum d+        Case_  e'  bs  ->+            op2 "case" (arg e') (opN "Branches" (mapleBranch <$> bs))+        Superpose_ pms ->+            opN "Msum" (uncurry (app2 "Weight") <$> L.toList pms)+        Reject_ _      -> showString "Msum()"+++mapleLiteral :: Literal a -> ShowS+mapleLiteral (LNat  v) = shows v+mapleLiteral (LInt  v) = parens (shows v)+mapleLiteral (LProb v) = showsRational v+mapleLiteral (LReal v) = showsRational v++showsRational :: (Integral a, Show a) => Ratio a -> ShowS+showsRational a =+    parens+        ( shows (numerator a)+        . showChar '/'+        . shows (denominator a)+        )+++var1 :: Variable (a :: Hakaru) -> ShowS+var1 x | Text.null (varHint x) = showChar 'x' . (shows . fromNat . varID) x+       | otherwise             = showString (Text.unpack (varHint x))++list1vars :: List1 Variable (vars :: [Hakaru]) -> [String]+list1vars Nil1         = []+list1vars (Cons1 x xs) = var1 x [] : list1vars xs++mapleSCon :: (ABT Term abt) => SCon args a -> SArgs abt args -> ShowS+mapleSCon Lam_ = \(e1 :* End) ->+    caseBind e1 $ \x e1' ->+        op3 "lam" (var1 x) (mapleType $ varType x) (arg e1')+mapleSCon App_ = \(e1 :* e2 :* End) -> app2 "app" e1 e2+mapleSCon Let_ = \(e1 :* e2 :* End) ->+    caseBind e2 $ \x e2' ->+        op2 "eval" (arg e2') (var x `meq` e1)+mapleSCon (CoerceTo_   _) = \(e :* End) -> arg e+mapleSCon (UnsafeFrom_ _) = \(e :* End) -> arg e+mapleSCon (PrimOp_    o) = \es          -> maplePrimOp    o es+mapleSCon (ArrayOp_   o) = \es          -> mapleArrayOp   o es+mapleSCon (MeasureOp_ o) = \es          -> mapleMeasureOp o es+mapleSCon Dirac          = \(e1 :* End) -> app1 "Ret" e1+mapleSCon MBind          = \(e1 :* e2 :* End) ->+    caseBind e2 $ \x e2' ->+        app3 "Bind"  e1 (var x) e2'+mapleSCon Plate = \(e1 :* e2 :* End) ->+    caseBind e2 $ \x e2' ->+        app3 "Plate" e1 (var x) e2'+mapleSCon Chain = \(e1 :* e2 :* e3 :* End) ->+    error "TODO: mapleSCon{Chain}"+mapleSCon Integrate = \(e1 :* e2 :* e3 :* End) ->+    caseBind e3 $ \x e3' ->+        showString "int("+        . arg e3'+        . showString ", ["+        . var1 x+        . showChar '='+        . arg e1+        . showString ".."+        . arg e2+        . showString "])"+mapleSCon (Summate _ _) = \(e1 :* e2 :* e3 :* End) ->+    caseBind e3 $ \x e3' ->+        showString "sum("+        . arg e3'+        . showString ", "+        . var1 x+        . showChar '='+        . arg e1+        . showString "..("+        . arg e2+        . showString ")-1)"+mapleSCon (Product _ _) = \(e1 :* e2 :* e3 :* End) ->+    caseBind e3 $ \x e3' ->+        showString "product("+        . arg e3'+        . showString ", "+        . var1 x+        . showChar '='+        . arg e1+        . showString "..("+        . arg e2+        . showString ")-1)"+mapleSCon Expect = \(e1 :* e2 :* End) ->+    error "TODO: mapleSCon{Expect}"+    {-+    caseBind e2 $ \x e2' ->+    arg+        . expect e1+        . binder Text.empty (varType x)+        $ \x' -> subst x x' e2'+    -}+++mapleNary :: (ABT Term abt) => NaryOp a -> Seq (abt '[] a) -> ShowS+mapleNary And      = appN "And"+mapleNary (Sum  _) = parens . intercalate (showString " + ") . fmap arg+mapleNary (Prod _) = parens . intercalate (showString " * ") . fmap arg+mapleNary (Min _)  = appN "min"+mapleNary (Max _)  = appN "max"+mapleNary op       = error $ "TODO: mapleNary{" ++ show op ++ "}"+++mapleDatum :: (ABT Term abt) => Datum (abt '[]) t -> ShowS+mapleDatum (Datum hint _ d) =+    op2 "Datum"+        (showString (Text.unpack hint))+        (mapleDatumCode d)++mapleDatumCode :: (ABT Term abt) => DatumCode xss (abt '[]) a -> ShowS+mapleDatumCode (Inr d) = op1 "Inr" (mapleDatumCode   d)+mapleDatumCode (Inl d) = op1 "Inl" (mapleDatumStruct d)++mapleDatumStruct :: (ABT Term abt) => DatumStruct xs (abt '[]) a -> ShowS+mapleDatumStruct Done       = showString "Done"+mapleDatumStruct (Et d1 d2) =+    op2 "Et" (mapleDatumFun d1) (mapleDatumStruct d2)++mapleDatumFun :: (ABT Term abt) => DatumFun x (abt '[]) a -> ShowS+mapleDatumFun (Konst a) = app1 "Konst" a+mapleDatumFun (Ident a) = app1 "Ident" a+++-- TODO: if we really wanted we could create an indexed variant of+-- 'State' to keep track of the length of the list of variables,+-- to guarantee the two error cases can never occur.+mapleBranch :: (ABT Term abt) => Branch a abt b -> ShowS+mapleBranch (Branch pat e) =+    let (vars, e')    = caseBinds e+        (pat', vars') = runState (maplePattern pat) (list1vars vars)+    in+    case vars' of+    _:_ -> error "mapleBranch: didn't use all the variable names"+    []  -> op2 "Branch" pat' (arg e')++maplePattern :: Pattern xs a -> State [String] ShowS+maplePattern PWild = return $ showString "PWild"+maplePattern PVar  = do+    vs <- get+    case vs of+        []    -> error "maplePattern: ran out of variable names"+        v:vs' -> do+            put vs'+            return $ op1 "PVar" (showString v)+maplePattern (PDatum hint pat) =+    op2 "PDatum" (showString $ Text.unpack hint) <$> maplePDatumCode pat++maplePDatumCode :: PDatumCode xss vars a -> State [String] ShowS+maplePDatumCode (PInr pat) = op1 "PInr" <$> maplePDatumCode pat+maplePDatumCode (PInl pat) = op1 "PInl" <$> maplePDatumStruct pat++maplePDatumStruct :: PDatumStruct xs vars a -> State [String] ShowS+maplePDatumStruct PDone           = return $ showString "PDone"+maplePDatumStruct (PEt pat1 pat2) =+    op2 "PEt"+        <$> maplePDatumFun    pat1+        <*> maplePDatumStruct pat2++maplePDatumFun :: PDatumFun x vars a -> State [String] ShowS+maplePDatumFun (PKonst pat) = op1 "PKonst" <$> maplePattern pat+maplePDatumFun (PIdent pat) = op1 "PIdent" <$> maplePattern pat+++arg :: (ABT Term abt) => abt '[] a -> ShowS+arg = mapleAST . LC_+++maplePrimOp+    :: (ABT Term abt, typs ~ UnLCs args, args ~ LCs typs)+    => PrimOp typs a -> SArgs abt args -> ShowS+maplePrimOp Not              (e1 :* End)       = app1 "Not" e1+maplePrimOp Pi               End               = showString "Pi"+maplePrimOp Cos              (e1 :* End)       = app1 "cos" e1+maplePrimOp RealPow          (e1 :* e2 :* End) =+    parens (arg e1 . showString " ^ " . arg e2)+maplePrimOp Exp              (e1 :* End)       = app1 "exp"  e1+maplePrimOp Log              (e1 :* End)       = app1 "log"  e1+maplePrimOp (Infinity  _)    End               = showString "infinity"+maplePrimOp GammaFunc        (e1 :* End)       = app1 "GAMMA" e1+maplePrimOp BetaFunc         (e1 :* e2 :* End) = app2 "Beta" e1 e2+maplePrimOp (Equal _)        (e1 :* e2 :* End) =+    parens (arg e1 . showString " = " . arg e2)+maplePrimOp (Less _)         (e1 :* e2 :* End) =+    arg e1 . showString " < " . arg e2+maplePrimOp (NatPow _)       (e1 :* e2 :* End) =+    parens (arg e1 . showString " ^ " . arg e2)+maplePrimOp (Negate _)       (e1 :* End)       = parens (app1 "-" e1)+maplePrimOp (Abs _)          (e1 :* End)       = app1 "abs"  e1+maplePrimOp (Recip   _)      (e1 :* End)       = app1 "1/"   e1+maplePrimOp (NatRoot _)      (e1 :* e2 :* End) = app2 "root" e1 e2+maplePrimOp x                _                 =+    error $ "TODO: maplePrimOp{" ++ show x ++ "}"++mapleArrayOp+    :: (ABT Term abt, typs ~ UnLCs args, args ~ LCs typs)+    => ArrayOp typs a -> SArgs abt args -> ShowS+mapleArrayOp (Index _) (e1 :* e2 :* End) = app2 "idx"  e1 e2+mapleArrayOp (Size  _) (e1 :* End)       = app1 "size" e1+mapleArrayOp _         _                 = error "TODO: mapleArrayOp{Reduce}"++mapleMeasureOp+    :: (ABT Term abt, typs ~ UnLCs args, args ~ LCs typs)+    => MeasureOp typs a -> SArgs abt args -> ShowS+mapleMeasureOp Lebesgue    = \End               -> showString "Lebesgue()"+mapleMeasureOp Counting    = \End               -> showString "Counting()"+mapleMeasureOp Categorical = \(e1 :* End)       -> app1 "Categorical" e1+mapleMeasureOp Uniform     = \(e1 :* e2 :* End) -> app2 "Uniform"  e1 e2+mapleMeasureOp Normal      = \(e1 :* e2 :* End) -> app2 "Gaussian" e1 e2+mapleMeasureOp Poisson     = \(e1 :* End)       -> app1 "PoissonD" e1+mapleMeasureOp Gamma       = \(e1 :* e2 :* End) -> app2 "GammaD"   e1 e2+mapleMeasureOp Beta        = \(e1 :* e2 :* End) -> app2 "BetaD"    e1 e2+++----------------------------------------------------------------+mapleType :: Sing (a :: Hakaru) -> ShowS+mapleType SNat         = showString "HInt(Bound(`>=`,0))"+mapleType SInt         = showString "HInt()"+mapleType SProb        = showString "HReal(Bound(`>=`,0))"+mapleType SReal        = showString "HReal()"+mapleType (SFun a b)   = op2 "HFunction" (mapleType a) (mapleType b)+mapleType (SArray a)   = op1 "HArray"    (mapleType a)+mapleType (SMeasure a) = op1 "HMeasure"  (mapleType a)+-- Special case pair+mapleType (SData (STyCon c `STyApp` _ `STyApp` _) (SPlus x SVoid))+    | isJust (jmEq1 c sSymbol_Pair)+    = showString "HData(DatumStruct(pair,["+    . mapleTypeDStruct x+    . showString "]))"+-- Special case unit+mapleType (SData (STyCon c) (SPlus SDone SVoid))+    | isJust (jmEq1 c sSymbol_Unit)+    = showString "HData(DatumStruct(unit,[]))"+-- Special case bool+mapleType (SData (STyCon c) (SPlus SDone (SPlus SDone SVoid)))+    | isJust (jmEq1 c sSymbol_Bool)+    = showString "HData(DatumStruct(true,[]),DatumStruct(false,[]))"+mapleType x = error $ "TODO: mapleType{" ++ show x ++ "}"++mapleTypeDStruct :: Sing (a :: [HakaruFun]) -> ShowS+mapleTypeDStruct SDone      = showString "NULL"+mapleTypeDStruct (SEt x xs) =+      mapleTypeDFun x+    . showString ","+    . mapleTypeDStruct xs++mapleTypeDFun :: Sing (a :: HakaruFun) -> ShowS+mapleTypeDFun (SKonst a) = op1 "Konst" (mapleType a)+mapleTypeDFun SIdent     = showString "Ident"++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Runtime/Prelude.hs view
@@ -0,0 +1,229 @@+{-# LANGUAGE CPP+           , GADTs+           , DataKinds+           , TypeFamilies+           , FlexibleContexts+           , UndecidableInstances+           , LambdaCase+           , OverloadedStrings+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs -fsimpl-tick-factor=1000 #-}+module Language.Hakaru.Runtime.Prelude where++#if __GLASGOW_HASKELL__ < 710+import           Data.Functor                    ((<$>))+import           Control.Applicative             (Applicative(..))+#endif+import           Data.Foldable                   as F+import qualified System.Random.MWC               as MWC+import qualified System.Random.MWC.Distributions as MWCD+import           Data.Number.Natural+import qualified Data.Vector                     as V+import qualified Data.Vector.Unboxed             as U+import qualified Data.Vector.Generic             as G+import           Control.Monad+import           Prelude                         hiding (product)++type family MinBoxVec (v1 :: * -> *) (v2 :: * -> *) :: * -> *+type instance MinBoxVec V.Vector v        = V.Vector+type instance MinBoxVec v        V.Vector = V.Vector+type instance MinBoxVec U.Vector U.Vector = U.Vector++type family MayBoxVec a :: * -> *+type instance MayBoxVec Int          = U.Vector+type instance MayBoxVec Double       = U.Vector+type instance MayBoxVec (U.Vector a) = V.Vector+type instance MayBoxVec (V.Vector a) = V.Vector+type instance MayBoxVec (a,b)        = MinBoxVec (MayBoxVec a) (MayBoxVec b)++lam :: (a -> b) -> a -> b+lam = id++app :: (a -> b) -> a -> b+app f x = f x++let_ :: a -> (a -> b) -> b+let_ x f = let x1 = x in f x1++ann_ :: a -> b -> b+ann_ _ a = a++newtype Measure a = Measure { unMeasure :: MWC.GenIO -> IO (Maybe a) }++instance Functor Measure where+    fmap  = liftM++instance Applicative Measure where+    pure x = Measure $ \_ -> return (Just x)+    (<*>)  = ap++instance Monad Measure where+    return  = pure+    m >>= f = Measure $ \g -> do+                          Just x <- unMeasure m g+                          unMeasure (f x) g++makeMeasure :: (MWC.GenIO -> IO a) -> Measure a+makeMeasure f = Measure $ \g -> Just <$> f g++uniform :: Double -> Double -> Measure Double+uniform lo hi = makeMeasure $ MWC.uniformR (lo, hi)++normal :: Double -> Double -> Measure Double+normal mu sd = makeMeasure $ MWCD.normal mu sd++beta :: Double -> Double -> Measure Double+beta a b = makeMeasure $ MWCD.beta a b++gamma :: Double -> Double -> Measure Double+gamma a b = makeMeasure $ MWCD.gamma a b++categorical :: MayBoxVec Double Double -> Measure Int+categorical a = makeMeasure (\g -> fromIntegral <$> MWCD.categorical a g)++plate :: (G.Vector (MayBoxVec a) a) =>+         Int -> (Int -> Measure a) -> Measure (MayBoxVec a a)+plate n f = G.generateM (fromIntegral n) $ \x ->+             f (fromIntegral x)++pair :: a -> b -> (a, b)+pair = (,)++true, false :: Bool+true  = True+false = False++unit :: ()+unit = ()++data Pattern = PVar | PWild+newtype Branch a b =+    Branch { extract :: a -> Maybe b }++ptrue, pfalse :: a -> Branch Bool a+ptrue  b = Branch { extract = extractBool True  b }+pfalse b = Branch { extract = extractBool False b }++extractBool :: Bool -> a -> Bool -> Maybe a+extractBool b a p | p == b     = Just a  +                  | otherwise  = Nothing++ppair :: Pattern -> Pattern -> (x -> y -> b) -> Branch (x,y) b+ppair PVar  PVar c = Branch { extract = (\(x,y) -> Just (c x y)) }+ppair _     _    _ = error "ppair: TODO"++case_ :: a -> [Branch a b] -> b+case_ e_ bs_ = go e_ bs_+  where go _ []     = error "case_: unable to match any branches"+        go e (b:bs) = case extract b e of+                        Just b' -> b'+                        Nothing -> go e bs++branch :: (c -> Branch a b) -> c -> Branch a b+branch pat body = pat body++dirac :: a -> Measure a+dirac = return++pose :: Double -> Measure a -> Measure a+pose _ a = a++superpose :: [(Double, Measure a)]+          -> Measure a+superpose pms = do+  i <- makeMeasure $ MWCD.categorical (U.fromList $ map fst pms)+  snd (pms !! i)++reject :: Measure a+reject = Measure $ \_ -> return Nothing++nat_ :: Int -> Int+nat_ = id++int_ :: Int -> Int+int_ = id++unsafeNat :: Int -> Int+unsafeNat = id++nat2prob :: Int -> Double+nat2prob = fromIntegral++fromInt  :: Int -> Double+fromInt  = fromIntegral++nat2int  :: Int -> Int+nat2int  = id++nat2real :: Int -> Double+nat2real = fromIntegral++fromProb :: Double -> Double+fromProb = id++unsafeProb :: Double -> Double+unsafeProb = id++real_ :: Rational -> Double+real_ = fromRational++prob_ :: NonNegativeRational -> Double+prob_ = fromRational . fromNonNegativeRational++infinity :: Double+infinity = 1/0++abs_ :: Num a => a -> a+abs_ = abs++thRootOf :: Int -> Double -> Double+thRootOf a b = b ** (recip $ fromIntegral a)++array+    :: (G.Vector (MayBoxVec a) a)+    => Int+    -> (Int -> a)+    -> MayBoxVec a a+array n f = G.generate (fromIntegral n) (f . fromIntegral)++(!) :: (G.Vector (MayBoxVec a) a) => MayBoxVec a a -> Int -> a+a ! b = a G.! (fromIntegral b)++size :: (G.Vector (MayBoxVec a) a) => MayBoxVec a a -> Int+size v = fromIntegral (G.length v)++product+    :: Num a+    => Int+    -> Int+    -> (Int -> a)+    -> a+product a b f = F.foldl' (\x y -> x * f y) 1 [a .. b-1]++summate+    :: Num a+    => Int+    -> Int+    -> (Int -> a)+    -> a+summate a b f = F.foldl' (\x y -> x + f y) 0 [a .. b-1]++run :: Show a+    => MWC.GenIO+    -> Measure a+    -> IO ()+run g k = unMeasure k g >>= \case+           Just a  -> print a+           Nothing -> return ()++iterateM_+    :: Monad m+    => (a -> m a)+    -> a+    -> m b+iterateM_ f = g+    where g x = f x >>= g++withPrint :: Show a => (a -> IO b) -> a -> IO b+withPrint f x = print x >> f x
+ haskell/Language/Hakaru/Sample.hs view
@@ -0,0 +1,598 @@+{-# LANGUAGE CPP+           , GADTs+           , KindSignatures+           , TypeOperators+           , TypeFamilies+           , EmptyCase+           , DataKinds+           , PolyKinds+           , ExistentialQuantification+           , FlexibleContexts+           , OverloadedStrings+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}++module Language.Hakaru.Sample where++import           Numeric.SpecFunctions           (logGamma, logBeta, logFactorial)+import qualified Data.Number.LogFloat            as LF+-- import qualified Numeric.Integration.TanhSinh    as TS+import qualified System.Random.MWC               as MWC+import qualified System.Random.MWC.Distributions as MWCD+import qualified Data.Vector                     as V+import           Data.Sequence (Seq)+import qualified Data.Foldable                   as F+import qualified Data.List.NonEmpty              as L+import           Data.List.NonEmpty              (NonEmpty(..))+import           Data.Maybe                      (fromMaybe)+#if __GLASGOW_HASKELL__ < 710+import           Control.Applicative   (Applicative(..), (<$>))+#endif+import           Control.Monad.Identity+import           Control.Monad.Trans.Maybe+import           Control.Monad.State.Strict+import qualified Data.IntMap                     as IM++import Data.Number.Nat     (fromNat, unsafeNat)+import Data.Number.Natural (fromNatural, fromNonNegativeRational)+import Language.Hakaru.Types.DataKind+import Language.Hakaru.Types.Coercion+import Language.Hakaru.Types.Sing+import Language.Hakaru.Types.HClasses+import Language.Hakaru.Syntax.IClasses+import Language.Hakaru.Syntax.TypeOf+import Language.Hakaru.Syntax.Value+import Language.Hakaru.Syntax.Datum+import Language.Hakaru.Syntax.DatumCase+import Language.Hakaru.Syntax.AST+import Language.Hakaru.Syntax.ABT++data EAssoc =+    forall a. EAssoc {-# UNPACK #-} !(Variable a) !(Value a)++newtype Env = Env (IM.IntMap EAssoc)++emptyEnv :: Env+emptyEnv = Env IM.empty++updateEnv :: EAssoc -> Env -> Env+updateEnv v@(EAssoc x _) (Env xs) =+    Env $ IM.insert (fromNat $ varID x) v xs++lookupVar :: Variable a -> Env -> Maybe (Value a)+lookupVar x (Env env) = do+    EAssoc x' e' <- IM.lookup (fromNat $ varID x) env+    Refl         <- varEq x x'+    return e'++---------------------------------------------------------------++-- Makes use of Atkinson's algorithm as described in:+-- Monte Carlo Statistical Methods pg. 55+--+-- Further discussion at:+-- http://www.johndcook.com/blog/2010/06/14/generating-poisson-random-values/+poisson_rng :: Double -> MWC.GenIO -> IO Int+poisson_rng lambda g' = make_poisson g'+    where+    smu   = sqrt lambda+    b     = 0.931 + 2.53*smu+    a     = -0.059 + 0.02483*b+    vr    = 0.9277 - 3.6224/(b - 2)+    arep  = 1.1239 + 1.1368/(b - 3.4)+    lnlam = log lambda++    make_poisson :: MWC.GenIO -> IO Int+    make_poisson g = do+        u <- MWC.uniformR (-0.5,0.5) g+        v <- MWC.uniformR (0,1) g+        let us = 0.5 - abs u+            k = floor $ (2*a / us + b)*u + lambda + 0.43+        case () of+            () | us >= 0.07 && v <= vr -> return k+            () | k < 0                 -> make_poisson g+            () | us <= 0.013 && v > us -> make_poisson g+            () | accept_region us v k  -> return k+            _                          -> make_poisson g++    accept_region :: Double -> Double -> Int -> Bool+    accept_region us v k =+        log (v * arep / (a/(us*us)+b))+        <=+        -lambda + fromIntegral k * lnlam - logFactorial k+++normalize :: [Value 'HProb] -> (LF.LogFloat, Double, [Double])+normalize []          = (0, 0, [])+normalize [(VProb x)] = (x, 1, [1])+normalize xs          = (m, y, ys)+    where+    xs' = map (\(VProb x) -> x) xs+    m   = maximum xs'+    ys  = [ LF.fromLogFloat (x/m) | x <- xs' ]+    y   = sum ys+++normalizeVector+    :: Value ('HArray 'HProb) -> (LF.LogFloat, Double, V.Vector Double)+normalizeVector (VArray xs) =+    let xs' = V.map (\(VProb x) -> x) xs in+    case V.length xs of+    0 -> (0, 0, V.empty)+    1 -> (V.unsafeHead xs', 1, V.singleton 1)+    _ ->+        let m   = V.maximum xs'+            ys  = V.map (\x -> LF.fromLogFloat (x/m)) xs'+            y   = V.sum ys+        in (m, y, ys)++---------------------------------------------------------------++runEvaluate+    :: (ABT Term abt)+    => abt '[] a+    -> Value a+runEvaluate prog = evaluate prog emptyEnv++evaluate+    :: (ABT Term abt)+    => abt '[] a+    -> Env+    -> Value a+evaluate e env = caseVarSyn e (evaluateVar env) (flip evaluateTerm env)++evaluateVar :: Env -> Variable a -> Value a+evaluateVar env v =+    case lookupVar v env of+    Nothing -> error "variable not found!"+    Just a  -> a++evaluateTerm+    :: (ABT Term abt)+    => Term abt a+    -> Env+    -> Value a+evaluateTerm t env =+    case t of+    o :$ es       -> evaluateSCon    o es env+    NaryOp_  o es -> evaluateNaryOp  o es env+    Literal_ v    -> evaluateLiteral v+    Empty_   _    -> evaluateEmpty+    Array_   n es -> evaluateArray   n es env+    Datum_   d    -> evaluateDatum   d    env+    Case_    o es -> evaluateCase    o es env+    Superpose_ es -> evaluateSuperpose es env+    Reject_ _     -> VMeasure $ \_ _ -> return Nothing++evaluateSCon+    :: (ABT Term abt)+    => SCon args a+    -> SArgs abt args+    -> Env+    -> Value a+evaluateSCon Lam_ (e1 :* End) env =+    caseBind e1 $ \x e1' ->+        VLam $ \v -> evaluate e1' (updateEnv (EAssoc x v) env)+evaluateSCon App_ (e1 :* e2 :* End) env =+    case evaluate e1 env of+    VLam f -> f (evaluate e2 env)+    v      -> case v of {}+evaluateSCon Let_ (e1 :* e2 :* End) env =+    let v = evaluate e1 env+    in caseBind e2 $ \x e2' ->+        evaluate e2' (updateEnv (EAssoc x v) env)+evaluateSCon (CoerceTo_   c) (e1 :* End) env =+    coerceTo c $ evaluate e1 env+evaluateSCon (UnsafeFrom_ c) (e1 :* End) env =+    coerceFrom c $ evaluate e1 env+evaluateSCon (PrimOp_ o)     es env = evaluatePrimOp    o es env+evaluateSCon (ArrayOp_ o)    es env = evaluateArrayOp   o es env+evaluateSCon (MeasureOp_  m) es env = evaluateMeasureOp m es env+evaluateSCon Dirac           (e1 :* End) env =+    VMeasure $ \p _ -> return $ Just (evaluate e1 env, p)+evaluateSCon MBind (e1 :* e2 :* End) env =+    case evaluate e1 env of+    VMeasure m1 -> VMeasure $ \ p g -> do+        x <- m1 p g+        case x of+            Nothing -> return Nothing+            Just (a, p') ->+                caseBind e2 $ \x' e2' ->+                    case evaluate e2' (updateEnv (EAssoc x' a) env) of+                    VMeasure y -> y p' g+                    v          -> case v of {}+    v -> case v of {}++evaluateSCon Plate (n :* e2 :* End) env =+    case evaluate n env of+    VNat n' -> caseBind e2 $ \x e' ->+        VMeasure $ \(VProb p) g -> runMaybeT $ do+            (v', ps) <- fmap V.unzip . V.mapM (performMaybe g) $+                V.generate (fromNat n') $ \v ->+                    evaluate e' $+                    updateEnv (EAssoc x . VNat $ unsafeNat v) env+            return+                ( VArray v'+                , VProb $ p * V.product (V.map (\(VProb x) -> x) ps)+                )+    v -> case v of {}+    where+    performMaybe+        :: MWC.GenIO+        -> Value ('HMeasure a)+        -> MaybeT IO (Value a, Value 'HProb)+    performMaybe g (VMeasure m) = MaybeT $ m (VProb 1) g++evaluateSCon Chain (n :* s :* e :* End) env =+    case (evaluate n env, evaluate s env) of+    (VNat n', start) ->+        caseBind e $ \x e' ->+            let s' = VLam $ \v -> evaluate e' (updateEnv (EAssoc x v) env) in+            VMeasure (\(VProb p) g -> runMaybeT $ do+                (evaluates, sout) <- runStateT (replicateM (fromNat n') $ convert g s') start+                let (v', ps) = unzip evaluates+                    bodyType :: Sing ('HMeasure (HPair a b)) -> Sing ('HArray a)+                    bodyType = SArray . fst . sUnPair . sUnMeasure+                return+                    ( VDatum $ dPair_ (bodyType $ caseBind e (const typeOf)) (typeOf s)+                        (VArray . V.fromList $ v') sout+                    , VProb $ p * product (map (\(VProb x) -> x) ps)+                    ))+    v -> case v of {}+    where+    convert+        :: MWC.GenIO+        -> Value (s ':-> 'HMeasure (HPair a s))+        -> StateT (Value s) (MaybeT IO) (Value a, Value 'HProb)+    convert g (VLam f) = StateT $ \s' ->+        case f s' of+        VMeasure f' -> do+            (as'', p') <- MaybeT (f' (VProb 1) g)+            let (a, s'') = unPair as''+            return ((a, p'), s'')+        v -> case v of {}++    unPair :: Value (HPair a b) -> (Value a, Value b)+    unPair (VDatum (Datum "pair" _typ+        (Inl (Et (Konst a)+            (Et (Konst b) Done))))) = (a, b)+    unPair x = case x of {}++evaluateSCon (Summate hd hs) (e1 :* e2 :* e3 :* End) env =+    case (evaluate e1 env, evaluate e2 env) of+    (lo, hi) ->+        caseBind e3 $ \x e3' ->+            foldl (\t i ->+                   evalOp (Sum  hs) t $+                     evaluate e3' (updateEnv (EAssoc x i) env))+                  (identityElement $ Sum hs)+                  (enumFromUntilValue hd lo hi)+    v                        -> case v of {}++evaluateSCon (Product hd hs) (e1 :* e2 :* e3 :* End) env =+    case (evaluate e1 env, evaluate e2 env) of+    (lo, hi) ->+        caseBind e3 $ \x e3' ->+            foldl (\t i ->+                   evalOp (Prod hs) t $+                     evaluate e3' (updateEnv (EAssoc x i) env))+                  (identityElement $ Prod hs)+                  (enumFromUntilValue hd lo hi)+    v                        -> case v of {}++evaluateSCon s _ _ = error $ "TODO: evaluateSCon{" ++ show s ++ "}"++evaluatePrimOp+    ::  ( ABT Term abt, typs ~ UnLCs args, args ~ LCs typs)+    => PrimOp typs a+    -> SArgs abt args+    -> Env+    -> Value a+evaluatePrimOp Not (e1 :* End) env = +    case evaluate e1 env of        +      VDatum a -> if a == dTrue+                  then VDatum dFalse+                  else VDatum dTrue+      v        -> case v of {}++evaluatePrimOp Pi  End         _   = VProb . LF.logFloat $ pi+evaluatePrimOp Cos (e1 :* End) env =+    case evaluate e1 env of+      VReal v1 -> VReal . cos $ v1+      v        -> case v of {}+evaluatePrimOp RealPow (e1 :* e2 :* End) env =+    case (evaluate e1 env, evaluate e2 env) of+      (VProb v1, VReal v2) -> VProb $ LF.pow v1 v2+      v                    -> case v of {}+evaluatePrimOp Exp (e1 :* End) env =+    case evaluate e1 env of+      VReal v1 -> VProb . LF.logToLogFloat $ v1+      v        -> case v of {}+evaluatePrimOp (Infinity h) End _ =+    case h of+      HIntegrable_Nat  -> error "Can not evaluate infinity for natural numbers"+      HIntegrable_Prob -> VProb $ LF.logFloat LF.infinity++evaluatePrimOp (Equal _) (e1 :* e2 :* End) env =+    case (evaluate e1 env, evaluate e2 env) of+    (VNat  v1, VNat  v2) -> VDatum $ if v1 == v2 then dTrue else dFalse+    (VInt  v1, VInt  v2) -> VDatum $ if v1 == v2 then dTrue else dFalse+    (VProb v1, VProb v2) -> VDatum $ if v1 == v2 then dTrue else dFalse+    (VReal v1, VReal v2) -> VDatum $ if v1 == v2 then dTrue else dFalse+    v                    -> error "TODO: evaluatePrimOp{Equal}"+evaluatePrimOp (Less _) (e1 :* e2 :* End) env =+    case (evaluate e1 env, evaluate e2 env) of+    (VNat  v1, VNat  v2) -> VDatum $ if v1 < v2 then dTrue else dFalse+    (VProb v1, VProb v2) -> VDatum $ if v1 < v2 then dTrue else dFalse+    (VReal v1, VReal v2) -> VDatum $ if v1 < v2 then dTrue else dFalse+    v                    -> error "TODO: evaluatePrimOp{Less}"+evaluatePrimOp (NatPow _) (e1 :* e2 :* End) env = +    case evaluate e2 env of+    VNat  v2 ->+        let v2' = fromNat v2 in+        case evaluate e1 env of+          VNat  v1 -> VNat  (v1 ^ v2')+          VInt  v1 -> VInt  (v1 ^ v2')+          VProb v1 -> VProb (v1 ^ v2')+          VReal v1 -> VReal (v1 ^ v2')+    v2       -> case v2 of {}+evaluatePrimOp (Negate _) (e1 :* End) env = +    case evaluate e1 env of+    VInt  v -> VInt  (negate v)+    VReal v -> VReal (negate v)+    v       -> case v of {}+evaluatePrimOp (Abs   _) (e1 :* End) env =+    case evaluate e1 env of+    VInt  v -> VNat  . unsafeNat   $ abs v+    VReal v -> VProb . LF.logFloat $ abs v+    v       -> case v of {}+evaluatePrimOp (Recip _) (e1 :* End) env = +    case evaluate e1 env of+    VProb v -> VProb (recip v)+    VReal v -> VReal (recip v)+    v       -> case v of {}+evaluatePrimOp (NatRoot _) (e1 :* e2 :* End) env =+    case (evaluate e1 env, evaluate e2 env) of+    (VProb v1, VNat v2) -> VProb $ LF.pow v1 (recip . fromIntegral $ v2)+    v                   -> case v of {}    ++evaluatePrimOp prim _ _ =+    error ("TODO: evaluatePrimOp{" ++ show prim ++ "}")++evaluateArrayOp+    :: ( ABT Term abt+       , typs ~ UnLCs args+       , args ~ LCs typs)+    => ArrayOp typs a+    -> SArgs abt args+    -> Env+    -> Value a+evaluateArrayOp (Index _) = \(e1 :* e2 :* End) env ->+    case (evaluate e1 env, evaluate e2 env) of+    (VArray v, VNat n) -> v V.! fromNat n+    _                  -> error "evaluateArrayOp: the impossible happened"++evaluateArrayOp (Size _) = \(e1 :* End) env ->+    case evaluate e1 env of+    VArray v -> VNat . unsafeNat $ V.length v+    _        -> error "evaluateArrayOp: the impossible happened"++evaluateArrayOp (Reduce _) = \(e1 :* e2 :* e3 :* End) env ->+    case ( evaluate e1 env+         , evaluate e2 env+         , evaluate e3 env) of+    (f, a, VArray v) -> V.foldl' (lam2 f) a v+    _                -> error "evaluateArrayOp: the impossible happened"++evaluateMeasureOp+    :: ( ABT Term abt+       , typs ~ UnLCs args+       , args ~ LCs typs)+    => MeasureOp typs a+    -> SArgs abt args+    -> Env+    -> Value ('HMeasure a)++evaluateMeasureOp Lebesgue = \End _ ->+    VMeasure $ \(VProb p) g -> do+        (u,b) <- MWC.uniform g+        let l = log u+        let n = -l+        return $ Just+            ( VReal $ if b then n else l+            , VProb $ p * 2 * LF.logToLogFloat n+            )++evaluateMeasureOp Counting = \End _ ->+    VMeasure $ \(VProb p) g -> do+        let success = LF.logToLogFloat (-3 :: Double)+        let pow x y = LF.logToLogFloat (LF.logFromLogFloat x *+                                       (fromIntegral y :: Double))+        u <- MWCD.geometric0 (LF.fromLogFloat success) g+        b <- MWC.uniform g+        return $ Just+            ( VInt  $ if b then -1-u else u+            , VProb $ p * 2 / pow (1-success) u / success)++evaluateMeasureOp Categorical = \(e1 :* End) env ->+    VMeasure $ \p g -> do+        let (_,y,ys) = normalizeVector (evaluate e1 env)+        if not (y > (0::Double)) -- TODO: why not use @y <= 0@ ??+        then error "Categorical needs positive weights"+        else do+            u <- MWC.uniformR (0, y) g+            return $ Just+                ( VNat+                . unsafeNat+                . fromMaybe 0+                . V.findIndex (u <=) +                . V.scanl1' (+)+                $ ys+                , p)++evaluateMeasureOp Uniform = \(e1 :* e2 :* End) env ->+    case (evaluate e1 env, evaluate e2 env) of+    (VReal v1, VReal v2) -> VMeasure $ \p g -> do+        x <- MWC.uniformR (v1, v2) g+        return $ Just (VReal x, p)+    _ -> error "evaluateMeasureOp: the impossible happened"++evaluateMeasureOp Normal = \(e1 :* e2 :* End) env ->+    case (evaluate e1 env, evaluate e2 env) of +    (VReal v1, VProb v2) -> VMeasure $ \ p g -> do+        x <- MWCD.normal v1 (LF.fromLogFloat v2) g+        return $ Just (VReal x, p)+    _ -> error "evaluateMeasureOp: the impossible happened"++evaluateMeasureOp Poisson = \(e1 :* End) env ->+    case evaluate e1 env of+    VProb v1 -> VMeasure $ \ p g -> do+        x <- poisson_rng (LF.fromLogFloat v1) g+        return $ Just (VNat $ unsafeNat x, p)+    _ -> error "evaluateMeasureOp: the impossible happened"++evaluateMeasureOp Gamma = \(e1 :* e2 :* End) env ->+    case (evaluate e1 env, evaluate e2 env) of +    (VProb v1, VProb v2) -> VMeasure $ \ p g -> do+        x <- MWCD.gamma (LF.fromLogFloat v1) (LF.fromLogFloat v2) g+        return $ Just (VProb $ LF.logFloat x, p)+    _ -> error "evaluateMeasureOp: the impossible happened"++evaluateMeasureOp Beta = \(e1 :* e2 :* End) env ->+    case (evaluate e1 env, evaluate e2 env) of +    (VProb v1, VProb v2) -> VMeasure $ \ p g -> do+        x <- MWCD.beta (LF.fromLogFloat v1) (LF.fromLogFloat v2) g+        return $ Just (VProb $ LF.logFloat x, p)+    _ -> error "evaluateMeasureOp: the impossible happened"++evaluateNaryOp+    :: (ABT Term abt)+    => NaryOp a -> Seq (abt '[] a) -> Env -> Value a+evaluateNaryOp s es =+    F.foldr (evalOp s) (identityElement s) . mapEvaluate es++identityElement :: NaryOp a -> Value a+identityElement And                   = VDatum dTrue+identityElement (Sum HSemiring_Nat)   = VNat  0+identityElement (Sum HSemiring_Int)   = VInt  0+identityElement (Sum HSemiring_Prob)  = VProb 0+identityElement (Sum HSemiring_Real)  = VReal 0+identityElement (Prod HSemiring_Nat)  = VNat  1+identityElement (Prod HSemiring_Int)  = VInt  1+identityElement (Prod HSemiring_Prob) = VProb 1+identityElement (Prod HSemiring_Real) = VReal 1+identityElement (Max  HOrd_Prob)      = VProb 0+identityElement (Max  HOrd_Real)      = VReal LF.negativeInfinity+identityElement (Min  HOrd_Prob)      = VProb (LF.logFloat LF.infinity)+identityElement (Min  HOrd_Real)      = VReal LF.infinity+++evalOp+    :: NaryOp a -> Value a -> Value a -> Value a+evalOp And (VDatum a) (VDatum b)        +    | a == dTrue && b == dTrue = VDatum dTrue+    | otherwise = VDatum dFalse+evalOp (Sum  HSemiring_Nat)  (VNat  a) (VNat  b) = VNat  (a + b)+evalOp (Sum  HSemiring_Int)  (VInt  a) (VInt  b) = VInt  (a + b)+evalOp (Sum  HSemiring_Prob) (VProb a) (VProb b) = VProb (a + b)+evalOp (Sum  HSemiring_Real) (VReal a) (VReal b) = VReal (a + b)+evalOp (Prod HSemiring_Nat)  (VNat  a) (VNat  b) = VNat  (a * b)+evalOp (Prod HSemiring_Int)  (VInt  a) (VInt  b) = VInt  (a * b)  +evalOp (Prod HSemiring_Prob) (VProb a) (VProb b) = VProb (a * b)  +evalOp (Prod HSemiring_Real) (VReal a) (VReal b) = VReal (a * b)+evalOp (Max  HOrd_Prob)      (VProb a) (VProb b) = VProb (max a b)+evalOp (Max  HOrd_Real)      (VReal a) (VReal b) = VReal (max a b)+evalOp (Min  HOrd_Prob)      (VProb a) (VProb b) = VProb (min a b) +evalOp (Min  HOrd_Real)      (VReal a) (VReal b) = VReal (min a b) ++evalOp op                    _          _        =+    error ("TODO: evalOp{" ++ show op ++ "}")++mapEvaluate+    :: (ABT Term abt)+    => Seq (abt '[] a) -> Env -> Seq (Value a)+mapEvaluate es env = fmap (flip evaluate env) es+++evaluateLiteral :: Literal a -> Value a+evaluateLiteral (LNat  n) = VNat  . fromInteger $ fromNatural n -- TODO: catch overflow errors+evaluateLiteral (LInt  n) = VInt  $ fromInteger n -- TODO: catch overflow errors+evaluateLiteral (LProb n) = VProb . fromRational $ fromNonNegativeRational n+evaluateLiteral (LReal n) = VReal $ fromRational n++evaluateEmpty :: Value ('HArray a)+evaluateEmpty = VArray V.empty++evaluateArray+    :: (ABT Term abt)+    => (abt '[] 'HNat)+    -> (abt '[ 'HNat ] a)+    -> Env+    -> Value ('HArray a)+evaluateArray n e env =+    case evaluate n env of+    VNat n' -> caseBind e $ \x e' ->+        VArray $ V.generate (fromNat n') $ \v ->+            let v' = VNat $ unsafeNat v in+            evaluate e' (updateEnv (EAssoc x v') env)++evaluateDatum+    :: (ABT Term abt)+    => Datum (abt '[]) (HData' a)+    -> Env+    -> Value (HData' a)+evaluateDatum d env = VDatum (fmap11 (flip evaluate env) d)++evaluateCase+    :: forall abt a b+    .  (ABT Term abt)+    => abt '[] a+    -> [Branch a abt b]+    -> Env+    -> Value b+evaluateCase o es env =+    case runIdentity $ matchBranches evaluateDatum' (evaluate o env) es of+    Just (Matched rho b) ->+        evaluate b (extendFromMatch (fromAssocs rho) env)+    _ -> error "Missing cases in match expression"+    where+    extendFromMatch :: [Assoc Value] -> Env -> Env+    extendFromMatch []                env' = env'+    extendFromMatch (Assoc x v : xvs) env' =+        extendFromMatch xvs (updateEnv (EAssoc x v) env')++    evaluateDatum' :: DatumEvaluator Value Identity+    evaluateDatum' = return . Just . getVDatum++    getVDatum :: Value (HData' a) -> Datum Value (HData' a)+    getVDatum (VDatum a) = a++evaluateSuperpose+    :: (ABT Term abt)+    => NonEmpty (abt '[] 'HProb, abt '[] ('HMeasure a))+    -> Env+    -> Value ('HMeasure a)+evaluateSuperpose ((q, m) :| []) env =+    case evaluate m env of+    VMeasure m' ->+        let VProb q' = evaluate q env+        in  VMeasure (\(VProb p) g -> m' (VProb $ p * q') g)+        +evaluateSuperpose pms@((_, m) :| _) env =+    case evaluate m env of+    VMeasure m' ->+        let pms'     = L.toList pms+            weights  = map ((flip evaluate env) . fst) pms'+            (x,y,ys) = normalize weights+        in VMeasure $ \(VProb p) g ->+            if not (y > (0::Double)) then return Nothing else do+            u <- MWC.uniformR (0, y) g+            case [ m1 | (v,(_,m1)) <- zip (scanl1 (+) ys) pms', u <= v ] of+                m2 : _ ->+                    case evaluate m2 env of+                    VMeasure m2' -> m2' (VProb $ p * x * LF.logFloat y) g+                []     -> m' (VProb $ p * x * LF.logFloat y) g++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Simplify.hs view
@@ -0,0 +1,108 @@+{-# LANGUAGE TypeSynonymInstances+           , FlexibleInstances+           , FlexibleContexts+           , DeriveDataTypeable+           , CPP+           , GADTs+           , DataKinds+           , OverloadedStrings+           , ScopedTypeVariables+           , TypeOperators+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.04.28+-- |+-- Module      :  Language.Hakaru.Simplify+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- Take strings from Maple and interpret them in Haskell (Hakaru)+----------------------------------------------------------------+module Language.Hakaru.Simplify+    ( simplify+    , simplifyDebug+    , MapleException(MapleException)+    ) where++import Control.Exception+import Control.Monad (when)++import qualified Language.Hakaru.Pretty.Maple as Maple++import Language.Hakaru.Parser.Maple+import Language.Hakaru.Parser.AST (Name)+import qualified Language.Hakaru.Parser.SymbolResolve as SR (resolveAST', fromVarSet)++import Language.Hakaru.Syntax.ABT+import Language.Hakaru.Syntax.AST+import Language.Hakaru.Syntax.TypeCheck+import Language.Hakaru.Syntax.TypeOf++import Language.Hakaru.Evaluation.ConstantPropagation++import Data.Typeable (Typeable)++import Data.Text (pack)+import System.MapleSSH (maple)+import System.IO++----------------------------------------------------------------++data MapleException       = MapleException String String+    deriving Typeable++-- Maple prints errors with "cursors" (^) which point to the specific position+-- of the error on the line above. The derived show instance doesn't preserve+-- positioning of the cursor.+instance Show MapleException where+    show (MapleException toMaple_ fromMaple) =+        "MapleException:\n" ++ fromMaple +++        "\nafter sending to Maple:\n" ++ toMaple_++instance Exception MapleException++simplify+    :: forall abt a+    .  (ABT Term abt) +    => abt '[] a -> IO (abt '[] a)+simplify = simplifyDebug False++simplifyDebug+    :: forall abt a+    .  (ABT Term abt) +    => Bool -> abt '[] a -> IO (abt '[] a)+simplifyDebug debug e = do+    let typ = typeOf e+    let toMaple_ = "use Hakaru, NewSLO in timelimit(90, RoundTrip("+                   ++ Maple.pretty e ++ ", " ++ Maple.mapleType typ ")) end use;"+    when debug (hPutStrLn stderr ("Sent to Maple:\n" ++ toMaple_))+    fromMaple <- maple toMaple_+    case fromMaple of+      '_':'I':'n':'e':'r':'t':_ -> do+        when debug $ do+          ret <- maple ("FromInert(" ++ fromMaple ++ ")")+          hPutStrLn stderr ("Returning from Maple:\n" ++ ret)+        either (throw  . MapleException toMaple_)+               (return . constantPropagation) $ do+          past <- leftShow $ parseMaple (pack fromMaple)+          let m = checkType typ+                   (SR.resolveAST' (getNames e) (maple2AST past))+          leftShow $ unTCM m (freeVars e) Nothing UnsafeMode+      _ -> throw (MapleException toMaple_ fromMaple)++    where+    leftShow :: forall b c. Show b => Either b c -> Either String c+    leftShow (Left err) = Left (show err)+    leftShow (Right x)  = Right x++    getNames :: abt '[] a -> [Name]+    getNames = SR.fromVarSet . freeVars+++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Syntax/ABT.hs view
@@ -0,0 +1,1046 @@+{-# LANGUAGE CPP+           , ScopedTypeVariables+           , GADTs+           , DataKinds+           , PolyKinds+           , TypeOperators+           , Rank2Types+           , MultiParamTypeClasses+           , FlexibleContexts+           , FlexibleInstances+           , FunctionalDependencies+           , UndecidableInstances+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.04.24+-- |+-- Module      :  Language.Hakaru.Syntax.ABT+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- The interface for abstract binding trees. Given the generating+-- functor 'Term': the non-recursive 'View' type extends 'Term' by+-- adding variables and binding; and each 'ABT' type (1) provides+-- some additional annotations at each recursion site, and then (2)+-- ties the knot to produce the recursive trees. For an introduction+-- to this technique\/approach, see:+--+--    * <http://semantic-domain.blogspot.co.uk/2015/03/abstract-binding-trees.html>+--    * <http://semantic-domain.blogspot.co.uk/2015/03/abstract-binding-trees-addendum.html>+--    * <http://winterkoninkje.dreamwidth.org/103978.html>+----------------------------------------------------------------+module Language.Hakaru.Syntax.ABT+    (+    -- * Our basic notion of variables.+      module Language.Hakaru.Syntax.Variable+    , resolveVar++    -- * The abstract binding tree interface+    -- See note about exposing 'View', 'viewABT', and 'unviewABT'+    , View(..)+    , unviewABT+    , ABT(..)+    , caseVarSyn+    , binds+    , binds_+    , caseBinds+    , underBinders+    , maxNextFree+    , maxNextBind+    , maxNextFreeOrBind+    -- ** Capture avoiding substitution for any 'ABT'+    , rename+    , renames+    , subst+    , substs+    -- ** Constructing first-order trees with a HOAS-like API+    -- cf., <http://comonad.com/reader/2014/fast-circular-substitution/>+    , binder+    -- *** Highly experimental+    -- , Hint(..)+    -- , multibinder+    , withMetadata+    -- ** Abstract nonsense+    , cataABT+    , paraABT++    -- * Some ABT instances+    , TrivialABT()+    , MemoizedABT()+    , MetaABT(..)+    ) where++import           Data.Text         (Text)+--import qualified Data.IntMap       as IM+import qualified Data.Foldable     as F+#if __GLASGOW_HASKELL__ < 710+import           Data.Monoid       (Monoid(..))+#endif++import Data.Number.Nat+import Language.Hakaru.Syntax.IClasses+-- TODO: factor the definition of the 'Sing' type family out from+-- the instances, so that we can make our ABT stuff totally independent+-- of the definition of Hakaru's types.+import Language.Hakaru.Types.Sing+import Language.Hakaru.Syntax.Variable++#ifdef __TRACE_DISINTEGRATE__+import Debug.Trace (trace)+#endif++----------------------------------------------------------------+----------------------------------------------------------------+-- TODO: (probably) parameterize the 'ABT' class over it's+-- implementation of 'Variable', so that after we're done constructing+-- terms with 'binder' we can make the varID strict\/unboxed.++-- TODO: (maybe) parameterize the 'ABT' class over it's implementation+-- of 'View' so that we can unpack the implementation of 'Variable'+-- into the 'Var' constructor. That is, the current version does+-- this unpacking, but if we parameterize the variable implementation+-- then we'd lose it; so this would allow us to regain it. Also,+-- if we do this, then 'MemoizedABT' could define it's own specialized+-- 'Bind' in order to keep track of whether bound variables occur+-- or not (for defining 'caseBind' precisely).+++----------------------------------------------------------------+-- | The raw view of abstract binding trees, to separate out variables+-- and binders from (1) the rest of syntax (cf., 'Term'), and (2)+-- whatever annotations (cf., the 'ABT' instances).+--+-- The first parameter gives the generating signature for the+-- signature. The second index gives the number and types of+-- locally-bound variables. And the final parameter gives the type+-- of the whole expression.+--+-- HACK: We only want to expose the patterns generated by this type,+-- not the constructors themselves. That way, callers must use the+-- smart constructors of the ABT class. But if we don't expose this+-- type, then clients can't define their own ABT instances (without+-- reinventing their own copy of this type)...+data View :: (k -> *) -> [k] -> k -> * where+    -- BUG: haddock doesn't like annotations on GADT constructors+    -- <https://github.com/hakaru-dev/hakaru/issues/6>++    -- Some syntax from the generating signature @rec@.+    Syn  :: !(rec a) -> View rec '[] a++    -- A variable use.+    Var  :: {-# UNPACK #-} !(Variable a) -> View rec '[] a++    -- N.B., this constructor is recursive, thus minimizing the+    -- memory overhead of whatever annotations our ABT stores (we+    -- only annotate once, at the top of a chaing of 'Bind's, rather+    -- than before each one). However, in the 'ABT' class, we provide+    -- an API as if things went straight back to @abt@. Doing so+    -- requires that 'caseBind' is part of the class so that we+    -- can push whatever annotations down over one single level of+    -- 'Bind', rather than pushing over all of them at once and+    -- then needing to reconstruct all but the first one.+    --+    -- A variable binding.+    Bind+        :: {-# UNPACK #-} !(Variable a)+        -> !(View rec xs b)+        -> View rec (a ': xs) b+++instance Functor12 View where+    fmap12 f (Syn  t)   = Syn  (f t)+    fmap12 _ (Var  x)   = Var  x+    fmap12 f (Bind x e) = Bind x (fmap12 f e)+++instance (Show1 (Sing :: k -> *), Show1 rec)+    => Show2 (View (rec :: k -> *))+    where+    showsPrec2 p (Syn  t)   = showParen_1  p "Syn"  t+    showsPrec2 p (Var  x)   = showParen_1  p "Var"  x+    showsPrec2 p (Bind x v) = showParen_12 p "Bind" x v++instance (Show1 (Sing :: k -> *), Show1 rec)+    => Show1 (View (rec :: k -> *) xs)+    where+    showsPrec1 = showsPrec2+    show1      = show2++-- TODO: could weaken the Show1 requirements to Show requirements...+instance (Show1 (Sing :: k -> *), Show1 rec)+    => Show (View (rec :: k -> *) xs a)+    where+    showsPrec = showsPrec1+    show      = show1+++-- TODO: neelk includes 'subst' as a method. Any reason we should?+-- TODO: jon includes instantiation as a method. Any reason we should?+-- TODO: require @(JmEq1 (Sing :: k -> *), Show1 (Sing :: k -> *), Foldable21 syn)@ since all our instances will need those too?+--+-- | The class interface for abstract binding trees. The first+-- argument, @syn@, gives the syntactic signature of the ABT;+-- whereas, the second argument, @abt@, is thing being declared as+-- an ABT for @syn@. The first three methods ('syn', 'var', 'bind')+-- alow us to inject any 'View' into the @abt@. The other methods+-- provide various views for extracting information from the @abt@.+--+-- At present we're using fundeps in order to restrict the relationship+-- between @abt@ and @syn@. However, in the future we may move @syn@+-- into being an associated type, if that helps to clean things up+-- (since fundeps and type families don't play well together). The+-- idea behind the fundep is that certain @abt@ implementations may+-- only be able to work for particular @syn@ signatures. This isn't+-- the case for 'TrivialABT' nor 'MemoizedABT', but isn't too+-- far-fetched.+class ABT (syn :: ([k] -> k -> *) -> k -> *) (abt :: [k] -> k -> *) | abt -> syn where+    -- Smart constructors for building a 'View' and then injecting it into the @abt@.+    syn  :: syn abt  a -> abt '[] a+    var  :: Variable a -> abt '[] a+    bind :: Variable a -> abt xs b -> abt (a ': xs) b++    -- TODO: better name. "unbind"? "fromBind"?+    --+    -- When the left side is defined, we have the following laws:+    -- > caseBind e bind == e+    -- > caseBind (bind x e) k == k x (unviewABT $ viewABT e)+    -- However, we do not necessarily have the following:+    -- > caseBind (bind x e) k == k x e+    -- because the definition of 'caseBind' for 'MemoizedABT'+    -- is not exact.+    --+    -- | Since the first argument to @abt@ is not @'[]@, we know+    -- it must be 'Bind'. So we do case analysis on that constructor,+    -- pushing the annotation down one binder (but not over the+    -- whole recursive 'View' layer).+    caseBind :: abt (x ': xs) a -> (Variable x -> abt xs a -> r) -> r++    -- See note about exposing 'View', 'viewABT', and 'unviewABT'.+    -- We could replace 'viewABT' with a case-elimination version...+    viewABT  :: abt xs a -> View (syn abt) xs a++    freeVars :: abt xs a -> VarSet (KindOf a)++    -- | Return the successor of the largest 'varID' of /free/+    -- variables. Thus, if there are no free variables we return+    -- zero. The default implementation is to take the successor+    -- of the maximum of 'freeVars'. This is part of the class in+    -- case you want to memoize it.+    --+    -- This function is used in order to generate guaranteed-fresh+    -- variables without the need for a name supply. In particular,+    -- it's used to ensure that the generated variable don't capture+    -- any free variables in the term.+    --+    -- * /Default:/ @nextFree = 'nextVarID' . 'freeVars'@+    nextFree :: abt xs a -> Nat+    nextFree = nextVarID . freeVars++    -- | Return the successor of the largest 'varID' of variable+    -- /binding sites/ (i.e., of variables bound by the 'Bind'+    -- constructor). Thus, if there are no binders, then we will+    -- return zero. N.B., this should return zero for /uses/ of the+    -- bound variables themselves. This is part of the class in+    -- case you want to memoize it.+    --+    -- This function is used in order to generate guaranteed-fresh+    -- variables without the need for a name supply. In particular,+    -- it's used to ensure that the generated variable won't be+    -- captured or shadowed by bindings already in the term.+    nextBind :: abt xs a -> Nat+++    -- | Return the maximum of 'nextFree' and 'nextBind'. For when+    -- you want to be really paranoid about choosing new variable+    -- IDs. In principle this shouldn't be necessary since we should+    -- always freshen things when going under binders; but for some+    -- reason only using 'nextFree' keeps leading to bugs in+    -- transformations like disintegration and expectation.+    --+    -- /N.B./, it is impossible to implement this function such+    -- that it is lazy in the bound variables like 'nextBind' is.+    -- Thus, it cannot be used for knot-tying tricks like 'nextBind'+    -- can.+    --+    -- * /Default:/ @nextFreeOrBind e = 'nextFree' e `max` 'nextBind' e@+    nextFreeOrBind :: abt xs a -> Nat+    nextFreeOrBind e = nextFree e `max` nextBind e+++    -- TODO: add a function for checking alpha-equivalence? Refreshing all variable IDs to be in some canonical form? Other stuff?+++-- See note about exposing 'View', 'viewABT', and 'unviewABT'+unviewABT :: (ABT syn abt) => View (syn abt) xs a -> abt xs a+unviewABT (Syn  t)   = syn  t+unviewABT (Var  x)   = var  x+unviewABT (Bind x v) = bind x (unviewABT v)+++-- | Since the first argument to @abt@ is @'[]@, we know it must+-- be either 'Syn' of 'Var'. So we do case analysis with those two+-- constructors.+caseVarSyn+    :: (ABT syn abt)+    => abt '[] a+    -> (Variable a -> r)+    -> (syn abt  a -> r)+    -> r+caseVarSyn e var_ syn_ =+    case viewABT e of+    Syn t -> syn_ t+    Var x -> var_ x+++-- | Call 'bind' repeatedly.+binds :: (ABT syn abt) => List1 Variable xs -> abt ys b -> abt (xs ++ ys) b+binds Nil1         e = e+binds (Cons1 x xs) e = bind x (binds xs e)++-- | A specialization of 'binds' for when @ys ~ '[]@. We define+-- this to avoid the need for using 'eqAppendIdentity' on the result+-- of 'binds' itself.+binds_ :: (ABT syn abt) => List1 Variable xs -> abt '[] b -> abt xs b+binds_ Nil1         e = e+binds_ (Cons1 x xs) e = bind x (binds_ xs e)+++-- TODO: take a continuation so that the type more closely resembles 'caseBind'; or, remove the CPSing in 'caseBind' so it more closely resembles this+-- | Call 'caseBind' repeatedly. (Actually we use 'viewABT'.)+caseBinds :: (ABT syn abt) => abt xs a -> (List1 Variable xs, abt '[] a)+caseBinds = go . viewABT+    where+    go  :: (ABT syn abt)+        => View (syn abt) xs a -> (List1 Variable xs, abt '[] a)+    go (Syn  t)   = (Nil1, syn t)+    go (Var  x)   = (Nil1, var x)+    go (Bind x v) = let ~(xs,e) = go v in (Cons1 x xs, e)+++-- TODO: give better name+-- | Transform expression under binds+underBinders+    :: (ABT syn abt)+    => (abt '[] a -> abt '[] b)+    -> abt xs a+    -> abt xs b+underBinders f e =+    let (vars, e') = caseBinds e+    in binds_ vars (f e')+++-- | Call 'nextFree' on all the terms and return the maximum.+maxNextFree :: (ABT syn abt, F.Foldable f) => f (Some2 abt) -> Nat+maxNextFree = unMaxNat . F.foldMap (\(Some2 e) -> MaxNat $ nextFree e)++-- | Call 'nextBind' on all the terms and return the maximum.+maxNextBind :: (ABT syn abt, F.Foldable f) => f (Some2 abt) -> Nat+maxNextBind = unMaxNat . F.foldMap (\(Some2 e) -> MaxNat $ nextBind e)++-- | Call 'nextFreeOrBind' on all the terms and return the maximum.+maxNextFreeOrBind :: (ABT syn abt, F.Foldable f) => f (Some2 abt) -> Nat+maxNextFreeOrBind =+    unMaxNat . F.foldMap (\(Some2 e) -> MaxNat $ nextFreeOrBind e)+++----------------------------------------------------------------+----------------------------------------------------------------+-- | A trivial ABT with no annotations.+--+-- The 'Show' instance does not expose the raw underlying data+-- types, but rather prints the smart constructors 'var', 'syn',+-- and 'bind'. This makes things prettier, but also means that if+-- you paste the string into a Haskell file you can use it for any+-- 'ABT' instance.+--+-- The 'freeVars', 'nextFree', and 'nextBind' methods are all very+-- expensive for this ABT, because we have to traverse the term+-- every time we want to call them. The 'MemoizedABT' implementation+-- fixes this.+newtype TrivialABT (syn :: ([k] -> k -> *) -> k -> *) (xs :: [k]) (a :: k) =+    TrivialABT (View (syn (TrivialABT syn)) xs a)++instance (JmEq1 (Sing :: k -> *), Show1 (Sing :: k -> *), Foldable21 syn)+    => ABT (syn :: ([k] -> k -> *) -> k -> *) (TrivialABT syn)+    where+    syn  t                = TrivialABT (Syn  t)+    var  x                = TrivialABT (Var  x)+    bind x (TrivialABT v) = TrivialABT (Bind x v)++    caseBind (TrivialABT v) k =+        case v of+        Bind x v' -> k x (TrivialABT v')++    viewABT (TrivialABT v) = v++    freeVars = go . viewABT+        where+        go  :: View (syn (TrivialABT syn)) xs a+            -> VarSet (KindOf a)+        go (Syn  t)   = foldMap21 freeVars t+        go (Var  x)   = singletonVarSet x+        go (Bind x v) = deleteVarSet x (go v)++    -- N.B., we could make this implementation much faster by+    -- avoiding traversing under binders. Under the assumption that+    -- the largest binder is the outermost one, this optimization+    -- is sound; and indeed the 'binder' function maintains that+    -- invariant. (If implementing this optimization, we can+    -- distinguish the case of 'Syn' underneath 'Bind' vs a top-level+    -- 'Syn' by checking whether the accumulator @n@ is zero or+    -- not.) However, if the largest binder is not the outermost+    -- one, then it would return the wrong answer. Since the+    -- 'TrivialABT' type is mainly intended for testing rather than+    -- production use, we avoid using this optimization so as to+    -- err on the side of soundness.+    nextBind = go . viewABT+        where+        go :: View (syn (TrivialABT syn)) xs a -> Nat+        go (Syn  t)   = unMaxNat $ foldMap21 (MaxNat . nextBind) t+        go (Var  _)   = unMaxNat $ mempty -- We mustn't look at variable *uses*!+        go (Bind x v) = max (1 + varID x) (go v)+++    -- Deforest the intermediate 'VarSet' of the default 'nextFree'+    -- implementation, and fuse the two passes of 'nextFree' and+    -- 'nextBind' into a single pass.+    nextFreeOrBind = go . viewABT+        where+        go :: View (syn (TrivialABT syn)) xs a -> Nat+        go (Syn  t)   = unMaxNat $ foldMap21 (MaxNat . nextFreeOrBind) t+        go (Var  x)   = 1 + varID x+        go (Bind x v) = max (1 + varID x) (go v)+++-- BUG: requires UndecidableInstances+instance (Show1 (Sing :: k -> *), Show1 (syn (TrivialABT syn)))+    => Show2 (TrivialABT (syn :: ([k] -> k -> *) -> k -> *))+    where+    {-+    -- Print the concrete data constructors:+    showsPrec2 p (TrivialABT v) =+        showParen (p > 9)+            ( showString "TrivialABT "+            . showsPrec1 11 v+            )+    -}+    -- Do something a bit prettier. (Because we print the smart+    -- constructors, this output can also be cut-and-pasted to work+    -- for any ABT instance.)+    showsPrec2 p (TrivialABT (Syn  t))   = showParen_1  p "syn"  t+    showsPrec2 p (TrivialABT (Var  x))   = showParen_1  p "var"  x+    showsPrec2 p (TrivialABT (Bind x v)) = showParen_11 p "bind" x (TrivialABT v)++instance (Show1 (Sing :: k -> *), Show1 (syn (TrivialABT syn)))+    => Show1 (TrivialABT (syn :: ([k] -> k -> *) -> k -> *) xs)+    where+    showsPrec1 = showsPrec2+    show1      = show2++-- TODO: could weaken the Show1 requirements to Show requirements...+instance (Show1 (Sing :: k -> *), Show1 (syn (TrivialABT syn)))+    => Show (TrivialABT (syn :: ([k] -> k -> *) -> k -> *) xs a)+    where+    showsPrec = showsPrec1+    show      = show1++----------------------------------------------------------------+-- TODO: replace @VarSet@ with @VarMap Nat@ where the+-- Nat is the number of times the variable occurs. That way, we can+-- tell when a bound variable is unused or only used only once (and+-- hence performing beta\/let reduction would be a guaranteed win),+-- and if it's used more than once then we can use the number of+-- occurances in our heuristic for deciding whether reduction would+-- be a win or not.+--+-- TODO: generalize this pattern for any monoidal annotation?+-- TODO: what is the performance cost of letting 'memoizedFreeVars' be lazy? Is it okay to lose the ability to use 'binder' in order to shore that up?+++-- WARNING: in older versions of the library, there was an issue+-- about the memoization of 'nextBind' breaking our ability to+-- tie-the-knot in 'binder'. Everything seems to work now, but it's+-- not entirely clear to me what changed...++-- | An ABT which memoizes 'freeVars', 'nextBind', and 'nextFree',+-- thereby making them take only /O(1)/ time.+--+-- N.B., the memoized set of free variables is lazy so that we can+-- tie-the-knot in 'binder' without interfering with our memos. The+-- memoized 'nextFree' must be lazy for the same reason.+data MemoizedABT (syn :: ([k] -> k -> *) -> k -> *) (xs :: [k]) (a :: k) =+    MemoizedABT+        { _memoizedFreeVars :: VarSet (KindOf a) -- N.B., lazy!+        , memoizedNextFree  :: Nat -- N.B., lazy!+        , memoizedNextBind  :: {-# UNPACK #-} !Nat+        , memoizedView      :: !(View (syn (MemoizedABT syn)) xs a)+        }++-- HACK: ""Cannot use record selector ‘_memoizedFreeVars’ as a function due to escaped type variables""+memoizedFreeVars :: MemoizedABT syn xs a -> VarSet (KindOf a)+memoizedFreeVars (MemoizedABT xs _ _ _) = xs+++instance (JmEq1 (Sing :: k -> *), Show1 (Sing :: k -> *), Foldable21 syn)+    => ABT (syn :: ([k] -> k -> *) -> k -> *) (MemoizedABT syn)+    where+    syn t =+        MemoizedABT+            (foldMap21 freeVars t)+            (unMaxNat $ foldMap21 (MaxNat . nextFree) t)+            (unMaxNat $ foldMap21 (MaxNat . nextBind) t)+            (Syn t)++    var x =+        MemoizedABT+            (singletonVarSet x)+            (1 + varID x)+            0+            (Var x)++    bind x (MemoizedABT xs _ nb v) =+        let xs' = deleteVarSet x xs+        in MemoizedABT+            xs'+            (nextVarID xs')+            ((1 + varID x) `max` nb)+            (Bind x v)++    -- N.B., when we go under the binder, the variable @x@ may not+    -- actually be used, but we add it to the set of freeVars+    -- anyways. The reasoning is thus: this function is mainly used+    -- in defining 'subst', and for that purpose it's important to+    -- track all the variables which /could be/ free, so that we+    -- can freshen appropriately. It may be safe to not include @x@+    -- when @x@ is not actually used in @v'@, but it's best not to+    -- risk it. Moreover, once we add support for open terms (i.e.,+    -- truly-free variables) then we'll need to account for the+    -- fact that the variable @x@ may come to be used in the grounding+    -- of the open term, even though it's not used in the part of+    -- the term we already know. Similarly, the true 'nextBind' may+    -- be lower now that we're going under this binding; but keeping+    -- it the same is an always valid approximation.+    --+    -- TODO: we could actually compute things exactly, similar to+    -- how we do it in 'syn'; but unclear if that's really worth it...+    caseBind (MemoizedABT xs nf nb v) k =+        case v of+        Bind x v' ->+            k x $ MemoizedABT+                (insertVarSet x xs)+                ((1 + varID x) `max` nf)+                nb+                v'++    viewABT  = memoizedView+    freeVars = memoizedFreeVars+    nextFree = memoizedNextFree+    nextBind = memoizedNextBind+++instance (Show1 (Sing :: k -> *), Show1 (syn (MemoizedABT syn)))+    => Show2 (MemoizedABT (syn :: ([k] -> k -> *) -> k -> *))+    where+    showsPrec2 p (MemoizedABT xs nf nb v) =+        showParen (p > 9)+            ( showString "MemoizedABT "+            . showsPrec  11 xs+            . showString " "+            . showsPrec  11 nf+            . showString " "+            . showsPrec  11 nb+            . showString " "+            . showsPrec1 11 v+            )++instance (Show1 (Sing :: k -> *), Show1 (syn (MemoizedABT syn)))+    => Show1 (MemoizedABT (syn :: ([k] -> k -> *) -> k -> *) xs)+    where+    showsPrec1 = showsPrec2+    show1      = show2++-- TODO: could weaken the Show1 requirements to Show requirements...+instance (Show1 (Sing :: k -> *), Show1 (syn (MemoizedABT syn)))+    => Show (MemoizedABT (syn :: ([k] -> k -> *) -> k -> *) xs a)+    where+    showsPrec = showsPrec1+    show      = show1++----------------------------------------------------------------+++-- | An ABT which carries around metadata at each node.+--+-- Right now this essentially inlines the the TrivialABT instance+-- but it would be nice if it was abstract in the choice of ABT.+data MetaABT+    (meta :: *)+    (syn  :: ([k] -> k -> *) -> k -> *)+    (xs   :: [k])+    (a    :: k) =+    MetaABT+    { getMetadata  :: !(Maybe meta)+    , metaView     :: !(View (syn (MetaABT meta syn)) xs a)+    }++withMetadata+    :: meta+    -> MetaABT meta syn xs a+    -> MetaABT meta syn xs a+withMetadata x (MetaABT _ v) = MetaABT (Just x) v++instance (JmEq1 (Sing :: k -> *), Show1 (Sing :: k -> *), Foldable21 syn)+    => ABT (syn :: ([k] -> k -> *) -> k -> *) (MetaABT meta syn)+    where+    syn t                   = MetaABT Nothing (Syn  t)+    var x                   = MetaABT Nothing (Var  x)+    bind x (MetaABT meta v) = MetaABT meta    (Bind x v)++    caseBind (MetaABT meta v) k =+        case v of+        Bind x v' -> k x (MetaABT meta v')++    viewABT  = metaView++    freeVars = go . viewABT+        where+        go  :: View (syn (MetaABT meta syn)) xs a+            -> VarSet (KindOf a)+        go (Syn  t)   = foldMap21 freeVars t+        go (Var  x)   = singletonVarSet x+        go (Bind x v) = deleteVarSet x (go v)++    nextBind = go . viewABT+        where+        go :: View (syn (MetaABT meta syn)) xs a -> Nat+        go (Syn  t)   = unMaxNat $ foldMap21 (MaxNat . nextBind) t+        go (Var  _)   = unMaxNat $ mempty+        go (Bind x v) = max (1 + varID x) (go v)+++    -- Deforest the intermediate 'VarSet' of the default 'nextFree'+    -- implementation, and fuse the two passes of 'nextFree' and+    -- 'nextBind' into a single pass.+    nextFreeOrBind = go . viewABT+        where+        go :: View (syn (MetaABT meta syn)) xs a -> Nat+        go (Syn  t)   = unMaxNat $ foldMap21 (MaxNat . nextFreeOrBind) t+        go (Var  x)   = 1 + varID x+        go (Bind x v) = max (1 + varID x) (go v)++++instance ( Show1 (Sing :: k -> *)+         , Show1 (syn (MetaABT meta syn))+         , Show  meta)+    => Show2 (MetaABT meta (syn :: ([k] -> k -> *) -> k -> *))+    where+    showsPrec2 p (MetaABT meta v) =+        showParen (p > 9)+            ( showString "MetaABT "+            . showsPrec  11 meta+            . showString " "+            . showsPrec1 11 v+            )++instance ( Show1 (Sing :: k -> *)+         , Show1 (syn (MetaABT meta syn))+         , Show  meta)+    => Show1 (MetaABT meta (syn :: ([k] -> k -> *) -> k -> *) xs)+    where+    showsPrec1 = showsPrec2+    show1      = show2++instance ( Show1 (Sing :: k -> *)+         , Show1 (syn (MetaABT meta syn))+         , Show  meta)+    => Show (MetaABT meta (syn :: ([k] -> k -> *) -> k -> *) xs a)+    where+    showsPrec = showsPrec1+    show      = show1+++----------------------------------------------------------------+----------------------------------------------------------------++-- TODO: do something smarter+-- | If the variable is in the set, then construct a new one which+-- isn't (but keeping the same hint and type as the old variable).+-- If it isn't in the set, then just return it.+freshen+    :: (JmEq1 (Sing :: k -> *), Show1 (Sing :: k -> *))+    => Variable (a :: k)+    -> VarSet (KindOf a)+    -> Variable a+freshen x xs+    | x `memberVarSet` xs = let i = nextVarID xs in i `seq` x{varID = i}+    | otherwise           = x+++-- TODO: reimplement this using 'cataABT' or 'paraABT'. Possibly make+-- strict versions of them in order to match the semantics we already+-- have about throwing 'VarEqTypeError' in a timely manner.+--+-- | Rename a free variable. Does nothing if the variable is bound.+rename+    :: forall syn abt (a :: k) xs (b :: k)+    .  (JmEq1 (Sing :: k -> *), Show1 (Sing :: k -> *), Functor21 syn, ABT syn abt)+    => Variable a+    -> Variable a+    -> abt xs b+    -> abt xs b+rename x y =+#ifdef __TRACE_DISINTEGRATE__+    trace ("renaming " ++ show (varID x)+           ++ " to " ++ show (varID y)) $+#endif           +    start+    where+    start :: forall xs' b'. abt xs' b' -> abt xs' b'+    start e = loop e (viewABT e)++    -- TODO: is it actually worth passing around the @e@? Benchmark.+    loop :: forall xs' b'. abt xs' b' -> View (syn abt) xs' b' -> abt xs' b'+    loop _ (Syn t) = syn $! fmap21 start t+    loop e (Var z) =+        case varEq x z of+        Just Refl -> var y+        Nothing   -> e+    loop e (Bind z v) =+#ifdef __TRACE_DISINTEGRATE__+        trace ("checking varEq "++ show (varID x) ++ " " ++ show (varID z)) $+#endif+        case varEq x z of+        Just Refl -> e+        Nothing   -> bind z $ loop (caseBind e $ const id) v+++-- TODO: reimplement this using 'cataABT' or 'paraABT'. Possibly make+-- strict versions of them in order to match the semantics we already+-- have about throwing 'VarEqTypeError' in a timely manner.+--+-- TODO: keep track of a variable renaming environment, and do+-- renaming on the fly rather than traversing the ABT repeatedly.+--+-- TODO: make an explicit distinction between substitution in general+-- vs instantiation of the top-level bound variable (i.e., the+-- function of type @abt (x ': xs) a -> abt '[] x -> abt xs a@).+-- cf., <http://hackage.haskell.org/package/abt>+--+-- | Perform capture-avoiding substitution. This function will+-- either preserve type-safety or else throw an 'VarEqTypeError'+-- (depending on which interpretation of 'varEq' is chosen). N.B.,+-- to ensure timely throwing of exceptions, the 'Term' and 'ABT'+-- should have strict 'fmap21' definitions.+subst+    :: forall syn abt (a :: k) xs (b :: k)+    .  (JmEq1 (Sing :: k -> *), Show1 (Sing :: k -> *), Functor21 syn, ABT syn abt)+    => Variable a+    -> abt '[]  a+    -> abt xs   b+    -> abt xs   b+subst x e =+#ifdef __TRACE_DISINTEGRATE__+    trace ("about to subst " ++ show (varID x)) $+#endif            +    start (maxNextFreeOrBind [Some2 (var x), Some2 e])+    where+    -- TODO: we could use the director-strings approach to optimize this (for MemoizedABT, but pessimizing for TrivialABT) by first checking whether @x@ is free in @f@; if so then recurse, if not then we're done.+    start :: forall xs' b'. Nat -> abt xs' b' -> abt xs' b'+    start n f = loop n f (viewABT f)++    -- TODO: is it actually worth passing around the @f@? Benchmark.+    loop :: forall xs' b'. Nat -> abt xs' b' -> View (syn abt) xs' b' -> abt xs' b'+    loop n _ (Syn t) = syn $! fmap21 (start n) t+    loop _ f (Var z) =+#ifdef __TRACE_DISINTEGRATE__+        trace ("checking varEq " ++ show (varID x) ++ " " ++ show (varID z)) $+#endif        +        case varEq x z of+        Just Refl -> e+        Nothing   -> f+    loop n f (Bind z _)+        | varID x == varID z = f+        | otherwise = +            -- TODO: even if we don't come up with a smarter way+            -- of freshening variables, it'd be better to just pass+            -- both sets to 'freshen' directly and then check them+            -- each; rather than paying for taking their union every+            -- time we go under a binder like this.+            let i  = 1 + max n (nextFreeOrBind f) -- (freeVars e `mappend` freeVars f)+                z' = i `seq` z{varID = i}+            -- HACK: the 'rename' function requires an ABT not a+            -- View, so we have to use 'caseBind' to give its+            -- input and then 'viewABT' to discard the topmost+            -- annotation. We really should find a way to eliminate+            -- that overhead.+            in caseBind f $ \_ f' ->+                   let f'' = rename z z' f' in+                   bind z' (loop i f'' (viewABT f''))++renames+    :: forall+        (syn :: ([k] -> k -> *) -> k -> *)+        (abt :: [k] -> k -> *)+        (xs  :: [k])+        (a   :: k)+    .   ( ABT syn abt+        , JmEq1 (Sing :: k -> *)+        , Show1 (Sing :: k -> *)+        , Functor21 syn+        )+    => Assocs (Variable :: k -> *)+    -> abt xs a+    -> abt xs a+renames rho0 =+    -- Guaranteed correct (since 'subst' is correct) but very inefficient+    \e0 -> F.foldl (\e (Assoc x v) -> rename x v e) e0 (unAssocs rho0)++{-+-- called (//) in Jon's abt library. We use this textual name so we can also have 'insts' for the n-ary version, rather than iterating the unary version. Or we could use something like (!) and (!!), albeit those names tend to be used to mean other things. It'd be nice to do (@) and (@@), but the first one is illegal.+inst+    :: forall syn abt (a :: k) xs (b :: k)+    .   ( JmEq1 (Sing :: k -> *)+        , Show1 (Sing :: k -> *)+        , Functor21 syn+        , ABT syn abt+        )+    => abt (a ': xs) b+    -> abt '[] a+    -> abt xs  b+inst f e =+    caseBind f $ \x f' ->+    subst x e f'+-}+++-- BUG: This appears to have both capture and escape issues as demonstrated by 'Tests.Disintegrate.test0' and commented on at 'Language.Hakaru.Evaluation.Types.runM'.+-- | The parallel version of 'subst' for performing multiple substitutions at once.+substs+    :: forall+        (syn :: ([k] -> k -> *) -> k -> *)+        (abt :: [k] -> k -> *)+        (xs  :: [k])+        (a   :: k)+    .   ( ABT syn abt+        , JmEq1 (Sing :: k -> *)+        , Show1 (Sing :: k -> *)+        , Functor21 syn+        )+    => Assocs (abt '[])+    -> abt xs a+    -> abt xs a+substs rho0 =+    -- Guaranteed correct (since 'subst' is correct) but very inefficient+    \e0 -> F.foldl (\e (Assoc x v) -> subst x v e) e0 (unAssocs rho0)+    {- -- old buggy version+    start rho0+    where+    fv0 :: VarSet (KindOf a)+    fv0 = F.foldMap (\(Assoc _ e) -> freeVars e) (unAssocs rho0)++    start :: forall xs' a'. Assocs abt -> abt xs' a' -> abt xs' a'+    start rho e = loop rho e (viewABT e)++    loop :: forall xs' a'+        . Assocs abt -> abt xs' a' -> View (syn abt) xs' a' -> abt xs' a'+    loop rho _ (Syn t) = syn $! fmap21 (start rho) t+    loop rho e (Var x) =+        case IM.lookup (fromNat $ varID x) (unAssocs rho) of+        Nothing           -> e+        Just (Assoc y e') ->+            case varEq x y of+            Just Refl     -> e'+            Nothing       -> e+    loop rho e (Bind x _body) =+        case IM.lookup (fromNat $ varID x) (unAssocs rho) of+        Nothing          -> e+        Just (Assoc y _) ->+            case varEq x y of+            Just Refl ->+                let rho' = IM.delete (fromNat $ varID x) (unAssocs rho) in+                if IM.null rho'+                then e+                else caseBind e $ \_x body' ->+                        bind x . loop (Assocs rho') body' $ viewABT body'+            Nothing   ->+                -- TODO: even if we don't come up with a smarter way+                -- of freshening variables, it'd be better to just pass+                -- both sets to 'freshen' directly and then check them+                -- each; rather than paying for taking their union every+                -- time we go under a binder like this.+                let x' = freshen x (fv0 `mappend` freeVars e) in+                -- HACK: the 'rename' function requires an ABT not a+                -- View, so we have to use 'caseBind' to give its+                -- input and then 'viewABT' to discard the topmost+                -- annotation. We really should find a way to eliminate+                -- that overhead.+                caseBind e $ \_x body' ->+                    bind x' . loop rho body' . viewABT $ rename x x' body'+    -}+++----------------------------------------------------------------+----------------------------------------------------------------+-- | A combinator for defining a HOAS-like API for our syntax.+-- Because our 'Term' is first-order, we cannot actually have any+-- exotic terms in our language. In principle, this function could+-- be used to do exotic things when constructing those non-exotic+-- terms; however, trying to do anything other than change the+-- variable's name hint will cause things to explode (since it'll+-- interfere with our tying-the-knot).+--+-- N.B., if you manually construct free variables and use them in+-- the body (i.e., via 'var'), they may become captured by the new+-- binding introduced here! This is inevitable since 'nextBind'+-- never looks at variable /use sites/; it only ever looks at+-- /binding sites/. On the other hand, if you manually construct a+-- bound variable (i.e., manually calling 'bind' yourself), then+-- the new binding introduced here will respect the old binding and+-- avoid that variable ID.+binder+    :: (ABT syn abt)+    => Text                     -- ^ The variable's name hint+    -> Sing a                   -- ^ The variable's type+    -> (abt '[] a -> abt xs b)  -- ^ Build the binder's body from a variable+    -> abt (a ': xs) b+binder hint typ hoas = bind x body+    where+    body = hoas (var x)+    x    = Variable hint (nextBind body) typ+    -- N.B., cannot use 'nextFree' when deciding the 'varID' of @x@++{-+data Hint (a :: k)+    = Hint !Text !(Sing a)++instance Show1 Hint where+    showsPrec1 p (Hint x s) = showParen_01 p "Hint" x s++instance Show (Hint a) where+    showsPrec = showsPrec1+    show      = show1++data VS (a :: k)+    = VS {-# UNPACK #-} !Variable !(Sing a)++-- this typechecks, and it works!+-- BUG: but it seems fairly unusable. We must give explicit type signatures to any lambdas passed as the second argument, otherwise it complains about not knowing enough about the types in @xs@... Also, the uncurriedness of it isn't very HOAS-like+multibinder+    :: (ABT abt) => List1 Hint xs -> (List1 abt xs -> abt b) -> abt b+multibinder names hoas = binds vars body+    where+    vars = go 0 names+        where+        -- BUG: this puts the largest binder on the inside+        go :: Nat -> List1 Hint xs -> List1 VS xs+        go _ Nil                         = Nil+        go n (Cons (Hint name typ) rest) =+            Cons (VS (Variable name (maxBind body + n) typ) typ)+                ((go $! n + 1) rest)+    body = hoas (go vars)+        where+        go :: ABT abt => List1 VS xs -> List1 abt xs+        go Nil                    = Nil+        go (Cons (VS x typ) rest) = Cons (var x typ) (go rest)++    binds :: ABT abt => List1 VS xs -> abt a -> abt a+    binds Nil                  = id+    binds (Cons (VS x _) rest) = bind x . binds rest+-}++----------------------------------------------------------------+----------------------------------------------------------------+-- TODO: versions of 'cataABT' and 'paraABT' which memoize the results for variables rather than recomputing them each time.++-- | The catamorphism (aka: iterator) for ABTs. While this is+-- equivalent to 'paraABT' in terms of the definable /functions/,+-- it is weaker in terms of definable /algorithms/. If you need+-- access to (subterms of) the original ABT, it is more efficient+-- to use 'paraABT' than to rebuild them. However, if you never+-- need access to the original ABT, then this function has somewhat+-- less overhead.+cataABT+    :: forall+        (abt :: [k] -> k -> *)+        (syn :: ([k] -> k -> *) -> k -> *)+        (r   :: [k] -> k -> *)+    .  (ABT syn abt, Functor21 syn)+    => (forall a.      Variable a -> r '[] a)+    -> (forall x xs a. Variable x -> r xs a -> r (x ': xs) a)+    -> (forall a.      syn r a    -> r '[] a)+    -> forall  xs a.   abt xs a   -> r xs a+cataABT var_ bind_ syn_ = start+    where+    start :: forall ys b. abt ys b -> r ys b+    start = loop . viewABT++    loop :: forall ys b. View (syn abt) ys b -> r ys b+    loop (Syn  t)   = syn_  (fmap21 start t)+    loop (Var  x)   = var_  x+    loop (Bind x e) = bind_ x (loop e)+{-# INLINE cataABT #-}+++-- | The paramorphism (aka: recursor) for ABTs. While this is+-- equivalent to 'cataABT' in terms of the definable /functions/,+-- it is stronger in terms of definable /algorithms/. If you need+-- access to (subterms of) the original ABT, it is more efficient+-- to use this function than to use 'cataABT' and rebuild them.+-- However, if you never need access to the original ABT, then+-- 'cataABT' has somewhat less overhead.+--+-- The provided type is slightly non-uniform since we inline (i.e.,+-- curry) the definition of 'Pair2' in the type of the @bind_@+-- argument. But we can't inline 'Pair2' away in the type of the+-- @syn_@ argument. N.B., if you treat the second component of the+-- 'Pair2' (either the real ones or the curried ones) lazily, then+-- this is a top-down function; however, if you treat them strictly+-- then it becomes a bottom-up function.+paraABT+    :: forall+        (abt :: [k] -> k -> *)+        (syn :: ([k] -> k -> *) -> k -> *)+        (r   :: [k] -> k -> *)+    .  (ABT syn abt, Functor21 syn)+    => (forall a.      Variable a -> r '[] a)+    -> (forall x xs a. Variable x -> abt xs a -> r xs a -> r (x ': xs) a)+    -> (forall a.      syn (Pair2 abt r) a -> r '[] a)+    -> forall  xs a.   abt xs a -> r xs a+paraABT var_ bind_ syn_ = start+    where+    start :: forall ys b. abt ys b -> r ys b+    start = loop . viewABT++    loop :: forall ys b. View (syn abt) ys b -> r ys b+    loop (Syn  t)   = syn_  (fmap21 (\e -> Pair2 e (start e)) t)+    loop (Var  x)   = var_  x+    loop (Bind x e) = bind_ x (unviewABT e) (loop e)+        -- HACK: how can we avoid that call to 'unviewABT'?+{-# INLINE paraABT #-}+++----------------------------------------------------------------+----------------------------------------------------------------++-- TODO: Swap the argument order?+-- | If the expression is a variable, then look it up. Recursing+-- until we can finally return some syntax.+resolveVar+    :: (JmEq1 (Sing :: k -> *), Show1 (Sing :: k -> *), ABT syn abt)+    => abt '[] (a :: k)+    -> Assocs (abt '[])+    -> Either (Variable a) (syn abt a)+resolveVar e xs =+    flip (caseVarSyn e) Right $ \x ->+        case lookupAssoc x xs of+        Just e' -> resolveVar e' xs+        Nothing -> Left x++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Syntax/AST.hs view
@@ -0,0 +1,938 @@+{-# LANGUAGE CPP+           , DataKinds+           , PolyKinds+           , GADTs+           , StandaloneDeriving+           , TypeOperators+           , TypeFamilies+           , FlexibleContexts+           , UndecidableInstances+           , Rank2Types+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.02.21+-- |+-- Module      :  Language.Hakaru.Syntax.AST+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- The generating functor for the raw syntax, along with various+-- helper types. For a more tutorial sort of introduction to how+-- things are structured here and in "Language.Hakaru.Syntax.ABT",+-- see <http://winterkoninkje.dreamwidth.org/103978.html>+--+-- TODO: are we finally at the place where we can get rid of all+-- those annoying underscores?+--+-- TODO: what is the runtime cost of storing all these dictionary+-- singletons? For existential type variables, it should be the+-- same as using a type class constraint; but for non-existential+-- type variables it'll, what, double the size of the AST?+----------------------------------------------------------------+module Language.Hakaru.Syntax.AST+    (+    -- * Syntactic forms+      SCon(..)+    , SArgs(..)+    , Term(..)+    -- * Operators+    , LC, LCs, UnLCs+    , LC_(..)+    , NaryOp(..)+    , PrimOp(..)+    , ArrayOp(..)+    , MeasureOp(..)+    -- * Constant values+    , Literal(..)+    +    -- * implementation details+    , foldMapPairs+    , traversePairs+    ) where++import           Data.Sequence (Seq)+import qualified Data.Foldable as F+import qualified Data.List.NonEmpty as L+#if __GLASGOW_HASKELL__ < 710+import           Data.Monoid   (Monoid(..))+import           Control.Applicative+import           Data.Traversable+#endif++import           Control.Arrow ((***))+import           Data.Ratio    (numerator, denominator)++import Data.Number.Natural+import Language.Hakaru.Syntax.IClasses+import Language.Hakaru.Types.DataKind+import Language.Hakaru.Types.Sing+import Language.Hakaru.Types.HClasses+import Language.Hakaru.Types.Coercion+import Language.Hakaru.Syntax.Datum+import Language.Hakaru.Syntax.ABT (ABT(syn))++----------------------------------------------------------------+----------------------------------------------------------------+-- BUG: can't UNPACK 'Integer' and 'Natural' like we can for 'Int' and 'Nat'+--+-- | Numeric literals for the primitive numeric types. In addition+-- to being normal forms, these are also ground terms: that is, not+-- only are they closed (i.e., no free variables), they also have+-- no bound variables and thus no binding forms. Notably, we store+-- literals using exact types so that none of our program transformations+-- have to worry about issues like overflow or floating-point fuzz.+data Literal :: Hakaru -> * where+    LNat   :: !Natural -> Literal 'HNat+    LInt   :: !Integer -> Literal 'HInt+    LProb  :: {-# UNPACK #-} !NonNegativeRational -> Literal 'HProb+    LReal  :: {-# UNPACK #-} !Rational            -> Literal 'HReal++instance JmEq1 Literal where+    jmEq1 (LNat  x) (LNat  y) = if x == y then Just Refl else Nothing+    jmEq1 (LInt  x) (LInt  y) = if x == y then Just Refl else Nothing+    jmEq1 (LProb x) (LProb y) = if x == y then Just Refl else Nothing+    jmEq1 (LReal x) (LReal y) = if x == y then Just Refl else Nothing+    jmEq1 _         _         = Nothing++instance Eq1 Literal where+    eq1 (LNat  x) (LNat  y) = x == y+    eq1 (LInt  x) (LInt  y) = x == y+    eq1 (LProb x) (LProb y) = x == y+    eq1 (LReal x) (LReal y) = x == y+    eq1 _         _          = False++instance Eq (Literal a) where+    (==) = eq1++-- TODO: instance Read (Literal a)++instance Show1 Literal where+    showsPrec1 p t =+        case t of+        LNat  v -> showParen_0 p "LNat"  v+        LInt  v -> showParen_0 p "LInt"  v+        LProb v -> showParen_0 p "LProb" v -- TODO: pretty print as decimals instead of using the Show Rational instance+        LReal v -> showParen_0 p "LReal" v -- TODO: pretty print as decimals instead of using the Show Rational instance++instance Show (Literal a) where+    showsPrec = showsPrec1+    show      = show1+++-- TODO: first optimize the @Coercion a b@ to choose the most desirable of many equivalent paths?+instance Coerce Literal where+    coerceTo   CNil         v = v+    coerceTo   (CCons c cs) v = coerceTo cs (primCoerceTo c v)++    coerceFrom CNil         v = v+    coerceFrom (CCons c cs) v = primCoerceFrom c (coerceFrom cs v)++instance PrimCoerce Literal where+    primCoerceTo c =+        case c of+        Signed     HRing_Int        -> \(LNat  n) -> LInt  (nat2int   n)+        Signed     HRing_Real       -> \(LProb p) -> LReal (prob2real p)+        Continuous HContinuous_Prob -> \(LNat  n) -> LProb (nat2prob  n)+        Continuous HContinuous_Real -> \(LInt  i) -> LReal (int2real  i)+        where+        -- HACK: type signatures needed to avoid defaulting+        nat2int   :: Natural -> Integer+        nat2int   = fromNatural+        nat2prob  :: Natural -> NonNegativeRational+        nat2prob  = unsafeNonNegativeRational . toRational -- N.B., is actually safe here+        prob2real :: NonNegativeRational -> Rational+        prob2real = fromNonNegativeRational+        int2real  :: Integer -> Rational+        int2real  = fromIntegral++    primCoerceFrom c =+        case c of+        Signed     HRing_Int        -> \(LInt  i) -> LNat  (int2nat   i)+        Signed     HRing_Real       -> \(LReal r) -> LProb (real2prob r)+        Continuous HContinuous_Prob -> \(LProb p) -> LNat  (prob2nat  p)+        Continuous HContinuous_Real -> \(LReal r) -> LInt  (real2int  r)+        where+        -- HACK: type signatures needed to avoid defaulting+        -- TODO: how to handle the errors? Generate error code in hakaru? capture it in a monad?+        int2nat  :: Integer -> Natural+        int2nat x =+            case toNatural x of+            Just y  -> y+            Nothing -> error "primCoerceFrom@Literal: negative HInt"+        prob2nat :: NonNegativeRational -> Natural+        prob2nat x =+            if denominator x == 1+            then numerator x+            else error "primCoerceFrom@Literal: non-integral HProb"+        real2prob :: Rational -> NonNegativeRational+        real2prob x =+            case toNonNegativeRational x of+            Just y  -> y+            Nothing -> error "primCoerceFrom@Literal: negative HReal"+        real2int :: Rational -> Integer+        real2int x =+            if denominator x == 1+            then numerator x+            else error "primCoerceFrom@Literal: non-integral HReal"+++----------------------------------------------------------------+-- TODO: helper functions for splitting NaryOp_ into components to group up like things. (e.g., grouping all the Literals together so we can do constant propagation)++-- | Primitive associative n-ary functions. By flattening the trees+-- for associative operators, we can more easily perform equivalence+-- checking and pattern matching (e.g., to convert @exp (a * log+-- b)@ into @b ** a@, regardless of whether @a@ is a product of+-- things or not). Notably, because of this encoding, we encode+-- things like subtraction and division by their unary operators+-- (negation and reciprocal).+--+-- We do not make any assumptions about whether these semigroups+-- are monoids, commutative, idempotent, or anything else. That has+-- to be handled by transformations, rather than by the AST itself.+data NaryOp :: Hakaru -> * where+    And  :: NaryOp HBool+    Or   :: NaryOp HBool+    Xor  :: NaryOp HBool+    -- N.B., even though 'Iff' is associative (in Boolean algebras),+    -- we should not support n-ary uses in our *surface* syntax.+    -- Because it's too easy for folks to confuse "a <=> b <=> c"+    -- with "(a <=> b) /\ (b <=> c)".+    Iff  :: NaryOp HBool -- == Not (Xor x y)++    -- These two don't necessarily have identity elements; thus,+    -- @NaryOp_ Min []@ and @NaryOp_ Max []@ may not be well-defined...+    -- TODO: check for those cases!+    Min  :: !(HOrd a) -> NaryOp a+    Max  :: !(HOrd a) -> NaryOp a++    Sum  :: !(HSemiring a) -> NaryOp a+    Prod :: !(HSemiring a) -> NaryOp a++    {-+    GCD  :: !(GCD_Domain a) -> NaryOp a+    LCM  :: !(GCD_Domain a) -> NaryOp a+    -}++-- TODO: instance Read (NaryOp a)+deriving instance Show (NaryOp a)++instance JmEq1 NaryOp where+    jmEq1 And      And      = Just Refl+    jmEq1 Or       Or       = Just Refl+    jmEq1 Xor      Xor      = Just Refl+    jmEq1 Iff      Iff      = Just Refl+    jmEq1 (Min  a) (Min  b) = jmEq1 (sing_HOrd a) (sing_HOrd b)+    jmEq1 (Max  a) (Max  b) = jmEq1 (sing_HOrd a) (sing_HOrd b)+    jmEq1 (Sum  a) (Sum  b) = jmEq1 a b+    jmEq1 (Prod a) (Prod b) = jmEq1 a b+    jmEq1 _        _        = Nothing++-- TODO: We could optimize this like we do for 'Literal'+instance Eq1 NaryOp where+    eq1 x y = maybe False (const True) (jmEq1 x y)++instance Eq (NaryOp a) where -- This one can be derived+    (==) = eq1+++----------------------------------------------------------------+-- TODO: should we define our own datakind for @([Hakaru], Hakaru)@ or perhaps for the @/\a -> ([a], Hakaru)@ part of it?++-- | Locally closed values (i.e., not binding forms) of a given type.+-- TODO: come up with a better name+type LC (a :: Hakaru) = '( '[], a )++-- BUG: how to declare that these are inverses?+type family LCs (xs :: [Hakaru]) :: [([Hakaru], Hakaru)] where+    LCs '[]       = '[]+    LCs (x ': xs) = LC x ': LCs xs++type family UnLCs (xs :: [([Hakaru], Hakaru)]) :: [Hakaru] where+    UnLCs '[]                  = '[]+    UnLCs ( '( '[], x ) ': xs) = x ': UnLCs xs+++-- | Simple primitive functions, and constants. N.B., nothing in+-- here should produce or consume things of 'HMeasure' or 'HArray'+-- type (except perhaps in a totally polymorphic way).+data PrimOp :: [Hakaru] -> Hakaru -> * where++    -- -- -- Here we have /monomorphic/ operators+    -- -- The Boolean operators+    -- TODO: most of these we'll want to optimize away according+    -- to some circuit-minimization procedure. But we're not+    -- committing to any particular minimal complete set of primops+    -- just yet.+    -- N.B., general circuit minimization problem is Sigma_2^P-complete,+    -- which is outside of PTIME; so we'll just have to approximate+    -- it for now, or link into something like Espresso or an+    -- implementation of Quine–McCluskey+    -- cf., <https://hackage.haskell.org/package/qm-0.1.0.0/candidate>+    -- cf., <https://github.com/pfpacket/Quine-McCluskey>+    -- cf., <https://gist.github.com/dsvictor94/8db2b399a95e301c259a>+    Not  :: PrimOp '[ HBool ] HBool+    -- And, Or, Xor, Iff+    Impl :: PrimOp '[ HBool, HBool ] HBool+    -- Impl x y == Or (Not x) y+    Diff :: PrimOp '[ HBool, HBool ] HBool+    -- Diff x y == Not (Impl x y)+    Nand :: PrimOp '[ HBool, HBool ] HBool+    -- Nand aka Alternative Denial, Sheffer stroke+    Nor  :: PrimOp '[ HBool, HBool ] HBool+    -- Nor aka Joint Denial, aka Quine dagger, aka Pierce arrow+    --+    -- The remaining eight binops are completely uninteresting:+    --   flip Impl+    --   flip Diff+    --   const+    --   flip const+    --   (Not .) . const == const . Not+    --   (Not .) . flip const+    --   const (const True)+    --   const (const False)+++    -- -- Trigonometry operators+    Pi    :: PrimOp '[] 'HProb -- TODO: maybe make this HContinuous polymorphic?+    -- TODO: if we're going to bother naming the hyperbolic ones, why not also name /a?(csc|sec|cot)h?/ eh?+    -- TODO: capture more domain information in these types?+    Sin   :: PrimOp '[ 'HReal ] 'HReal+    Cos   :: PrimOp '[ 'HReal ] 'HReal+    Tan   :: PrimOp '[ 'HReal ] 'HReal+    Asin  :: PrimOp '[ 'HReal ] 'HReal+    Acos  :: PrimOp '[ 'HReal ] 'HReal+    Atan  :: PrimOp '[ 'HReal ] 'HReal+    Sinh  :: PrimOp '[ 'HReal ] 'HReal+    Cosh  :: PrimOp '[ 'HReal ] 'HReal+    Tanh  :: PrimOp '[ 'HReal ] 'HReal+    Asinh :: PrimOp '[ 'HReal ] 'HReal+    Acosh :: PrimOp '[ 'HReal ] 'HReal+    Atanh :: PrimOp '[ 'HReal ] 'HReal+++    -- -- Other Real\/Prob-valued operators+    -- N.B., we only give the safe\/exact versions here. The old+    -- more lenient versions now require explicit coercions. Some+    -- of those coercions are safe, but others are not. This way+    -- we're explicit about where things can fail.+    -- N.B., we also have @NatPow{'HReal} :: 'HReal -> 'HNat -> 'HReal@,+    -- but non-integer real powers of negative reals are not real numbers!+    -- TODO: may need @SafeFrom_@ in order to branch on the input+    -- in order to provide the old unsafe behavior.+    RealPow   :: PrimOp '[ 'HProb, 'HReal ] 'HProb+    -- ComplexPow :: PrimOp '[ 'HProb, 'HComplex ] 'HComplex+    -- is uniquely well-defined. Though we may want to implement+    -- it via @r**z = ComplexExp (z * RealLog r)@+    -- Defining @HReal -> HComplex -> HComplex@ requires either+    -- multivalued functions, or a choice of complex logarithm and+    -- making it discontinuous.+    Exp       :: PrimOp '[ 'HReal ] 'HProb+    Log       :: PrimOp '[ 'HProb ] 'HReal+    -- TODO: Log1p, Expm1+    Infinity  :: HIntegrable a -> PrimOp '[] a+    -- TODO: add Factorial as the appropriate type restriction of GammaFunc?+    GammaFunc :: PrimOp '[ 'HReal ] 'HProb+    BetaFunc  :: PrimOp '[ 'HProb, 'HProb ] 'HProb+++    -- -- -- Here we have the /polymorphic/ operators++    -- -- HEq and HOrd operators+    -- TODO: equality doesn't make constructive sense on the reals...+    -- would it be better to constructivize our notion of total ordering?+    -- TODO: should we have LessEq as a primitive, rather than treating it as a macro?+    Equal :: !(HEq  a) -> PrimOp '[ a, a ] HBool+    Less  :: !(HOrd a) -> PrimOp '[ a, a ] HBool+++    -- -- HSemiring operators (the non-n-ary ones)+    NatPow :: !(HSemiring a) -> PrimOp '[ a, 'HNat ] a+    -- TODO: would it help to have a specialized version for when+    -- we happen to know that the 'HNat is a Literal? Same goes for+    -- the other powers\/roots+    --+    -- TODO: add a specialized version which returns NonNegative+    -- when the power is even? N.B., be sure not to actually constrain+    -- it to HRing (necessary for calling it \"NonNegative\")+++    -- -- HRing operators+    -- TODO: break these apart into a hierarchy of classes. N.B,+    -- there are two different interpretations of "abs" and "signum".+    -- On the one hand we can think of rings as being generated+    -- from semirings closed under subtraction/negation. From this+    -- perspective we have abs as a projection into the underlying+    -- semiring, and signum as a projection giving us the residual+    -- sign lost by the abs projection. On the other hand, we have+    -- the view of "abs" as a norm (i.e., distance to the "origin+    -- point"), which is the more common perspective for complex+    -- numbers and vector spaces; and relatedly, we have "signum"+    -- as returning the value on the unit (hyper)sphere, of the+    -- normalized unit vector. In another class, if we have a notion+    -- of an "origin axis" then we can have a function Arg which+    -- returns the angle to that axis, and therefore define signum+    -- in terms of Arg.+    -- Ring: Semiring + negate, abs, signum+    -- NormedLinearSpace: LinearSpace + originPoint, norm, Arg+    -- ??: NormedLinearSpace + originAxis, angle+    Negate :: !(HRing a) -> PrimOp '[ a ] a+    Abs    :: !(HRing a) -> PrimOp '[ a ] (NonNegative a)+    -- cf., <https://mail.haskell.org/pipermail/libraries/2013-April/019694.html>+    -- cf., <https://en.wikipedia.org/wiki/Sign_function#Complex_signum>+    -- Should we have Maple5's \"csgn\" as well as the usual \"sgn\"?+    -- Also note that the \"generalized signum\" anticommutes with Dirac delta!+    Signum :: !(HRing a) -> PrimOp '[ a ] a+    -- Law: x = coerceTo_ signed (abs_ x) * signum x+    -- More strictly/exactly, the result of Signum should be either+    -- zero or an @a@-unit value. For Int and Real, the units are+    -- +1 and -1. For Complex, the units are any point on the unit+    -- circle. For vectors, the units are any unit vector. Thus,+    -- more generally:+    -- Law : x = coerceTo_ signed (abs_ x) `scaleBy` signum x+    -- TODO: would it be worth defining the associated type of unit values for @a@? Probably...+    -- TODO: are there any salient types which support abs\/norm but+    -- do not have all units and thus do not support signum\/normalize?+++    -- -- HFractional operators+    Recip :: !(HFractional a) -> PrimOp '[ a ] a+    -- generates macro: IntPow+++    -- -- HRadical operators+    -- TODO: flip argument order to match our prelude's @thRootOf@?+    NatRoot :: !(HRadical a) -> PrimOp '[ a, 'HNat ] a+    -- generates macros: Sqrt, NonNegativeRationalPow, and RationalPow+++    -- -- HContinuous operators+    -- TODO: what goes here, if anything? cf., <https://en.wikipedia.org/wiki/Closed-form_expression#Comparison_of_different_classes_of_expressions>+    Erf :: !(HContinuous a) -> PrimOp '[ a ] a+    -- TODO: make Pi and Infinity HContinuous-polymorphic so that we can avoid the explicit coercion? Probably more mess than benefit.+++-- TODO: instance Read (PrimOp args a)+deriving instance Show (PrimOp args a)++instance JmEq2 PrimOp where+    jmEq2 Not         Not         = Just (Refl, Refl)+    jmEq2 Impl        Impl        = Just (Refl, Refl)+    jmEq2 Diff        Diff        = Just (Refl, Refl)+    jmEq2 Nand        Nand        = Just (Refl, Refl)+    jmEq2 Nor         Nor         = Just (Refl, Refl)+    jmEq2 Pi          Pi          = Just (Refl, Refl)+    jmEq2 Sin         Sin         = Just (Refl, Refl)+    jmEq2 Cos         Cos         = Just (Refl, Refl)+    jmEq2 Tan         Tan         = Just (Refl, Refl)+    jmEq2 Asin        Asin        = Just (Refl, Refl)+    jmEq2 Acos        Acos        = Just (Refl, Refl)+    jmEq2 Atan        Atan        = Just (Refl, Refl)+    jmEq2 Sinh        Sinh        = Just (Refl, Refl)+    jmEq2 Cosh        Cosh        = Just (Refl, Refl)+    jmEq2 Tanh        Tanh        = Just (Refl, Refl)+    jmEq2 Asinh       Asinh       = Just (Refl, Refl)+    jmEq2 Acosh       Acosh       = Just (Refl, Refl)+    jmEq2 Atanh       Atanh       = Just (Refl, Refl)+    jmEq2 RealPow     RealPow     = Just (Refl, Refl)+    jmEq2 Exp         Exp         = Just (Refl, Refl)+    jmEq2 Log         Log         = Just (Refl, Refl)+    jmEq2 GammaFunc   GammaFunc   = Just (Refl, Refl)+    jmEq2 BetaFunc    BetaFunc    = Just (Refl, Refl)+    jmEq2 (Equal a)   (Equal b)   =+        jmEq1 (sing_HEq a) (sing_HEq b) >>= \Refl ->+        Just (Refl, Refl)+    jmEq2 (Less a)    (Less b)    =+        jmEq1 (sing_HOrd a) (sing_HOrd b) >>= \Refl ->+        Just (Refl, Refl)+    jmEq2 (Infinity a) (Infinity b) =+        jmEq1 (sing_HIntegrable a) (sing_HIntegrable b) >>= \Refl ->+        Just (Refl, Refl)+    jmEq2 (NatPow   a) (NatPow   b) = jmEq1 a b >>= \Refl -> Just (Refl, Refl)+    jmEq2 (Negate   a) (Negate   b) = jmEq1 a b >>= \Refl -> Just (Refl, Refl)+    jmEq2 (Abs      a) (Abs      b) = jmEq1 a b >>= \Refl -> Just (Refl, Refl)+    jmEq2 (Signum   a) (Signum   b) = jmEq1 a b >>= \Refl -> Just (Refl, Refl)+    jmEq2 (Recip    a) (Recip    b) = jmEq1 a b >>= \Refl -> Just (Refl, Refl)+    jmEq2 (NatRoot  a) (NatRoot  b) = jmEq1 a b >>= \Refl -> Just (Refl, Refl)+    jmEq2 (Erf      a) (Erf      b) = jmEq1 a b >>= \Refl -> Just (Refl, Refl)+    jmEq2 _ _ = Nothing++-- TODO: We could optimize this like we do for 'Literal'+instance Eq2 PrimOp where+    eq2 x y = maybe False (const True) (jmEq2 x y)++instance Eq1 (PrimOp args) where+    eq1 = eq2++instance Eq (PrimOp args a) where -- This one can be derived+    (==) = eq1++----------------------------------------------------------------+-- | Primitive operators for consuming or transforming arrays.+--+-- TODO: we may want to replace the 'Sing' arguments with something+-- more specific in order to capture any restrictions on what can+-- be stored in an array. Or, if we can get rid of them entirely+-- while still implementing all the use sites of+-- 'Language.Hakaru.Syntax.AST.Sing.sing_ArrayOp', that'd be+-- better still.+data ArrayOp :: [Hakaru] -> Hakaru -> * where+    -- HACK: is there any way we can avoid storing the Sing values here, while still implementing 'sing_PrimOp'?+    Index  :: !(Sing a) -> ArrayOp '[ 'HArray a, 'HNat ] a+    Size   :: !(Sing a) -> ArrayOp '[ 'HArray a ] 'HNat+    -- The first argument should be a monoid, but we don't enforce+    -- that; it's the user's responsibility.+    Reduce :: !(Sing a) -> ArrayOp '[ a ':-> a ':-> a, a, 'HArray a ] a+    -- TODO: would it make sense to have a specialized version for when the first argument is some \"Op\", in order to avoid the need for lambdas?++-- TODO: instance Read (ArrayOp args a)+deriving instance Show (ArrayOp args a)++instance JmEq2 ArrayOp where+    jmEq2 (Index  a) (Index  b) = jmEq1 a b >>= \Refl -> Just (Refl, Refl)+    jmEq2 (Size   a) (Size   b) = jmEq1 a b >>= \Refl -> Just (Refl, Refl)+    jmEq2 (Reduce a) (Reduce b) = jmEq1 a b >>= \Refl -> Just (Refl, Refl)+    jmEq2 _          _          = Nothing++-- TODO: We could optimize this like we do for 'Literal'+instance Eq2 ArrayOp where+    eq2 x y = maybe False (const True) (jmEq2 x y)++instance Eq1 (ArrayOp args) where+    eq1 = eq2++instance Eq (ArrayOp args a) where -- This one can be derived+    (==) = eq1+++----------------------------------------------------------------+-- | Primitive operators to produce, consume, or transform+-- distributions\/measures. This corresponds to the old @Mochastic@+-- class, except that 'MBind' and 'Superpose_' are handled elsewhere+-- since they are not simple operators. (Also 'Dirac' is handled+-- elsewhere since it naturally fits with 'MBind', even though it+-- is a siple operator.)+--+-- TODO: we may want to replace the 'Sing' arguments with something+-- more specific in order to capture any restrictions on what can+-- be a measure space (e.g., to exclude functions). Or, if we can+-- get rid of them entirely while still implementing all the use+-- sites of 'Language.Hakaru.Syntax.AST.Sing.sing_MeasureOp',+-- that'd be better still.+data MeasureOp :: [Hakaru] -> Hakaru -> * where+    -- We might consider making Lebesgue and Counting polymorphic,+    -- since their restrictions to HProb and HNat are perfectly+    -- valid primitive measures. However, there are many other+    -- restrictions on measures we may want to consider, so handling+    -- these two here would only complicate matters.+    Lebesgue    :: MeasureOp '[]                 'HReal+    Counting    :: MeasureOp '[]                 'HInt+    Categorical :: MeasureOp '[ 'HArray 'HProb ] 'HNat+    -- TODO: make Uniform polymorphic, so that if the two inputs+    -- are HProb then we know the measure must be over HProb too.+    -- More generally, if the first input is HProb (since the second+    -- input is assumed to be greater thant he first); though that+    -- would be a bit ugly IMO.+    Uniform     :: MeasureOp '[ 'HReal, 'HReal ] 'HReal+    Normal      :: MeasureOp '[ 'HReal, 'HProb ] 'HReal+    Poisson     :: MeasureOp '[ 'HProb         ] 'HNat+    Gamma       :: MeasureOp '[ 'HProb, 'HProb ] 'HProb+    Beta        :: MeasureOp '[ 'HProb, 'HProb ] 'HProb++-- TODO: instance Read (MeasureOp typs a)+deriving instance Show (MeasureOp typs a)++instance JmEq2 MeasureOp where+    jmEq2 Lebesgue    Lebesgue    = Just (Refl, Refl)+    jmEq2 Counting    Counting    = Just (Refl, Refl)+    jmEq2 Categorical Categorical = Just (Refl, Refl)+    jmEq2 Uniform     Uniform     = Just (Refl, Refl)+    jmEq2 Normal      Normal      = Just (Refl, Refl)+    jmEq2 Poisson     Poisson     = Just (Refl, Refl)+    jmEq2 Gamma       Gamma       = Just (Refl, Refl)+    jmEq2 Beta        Beta        = Just (Refl, Refl)+    jmEq2 _           _           = Nothing++-- TODO: We could optimize this like we do for 'Literal'+instance Eq2 MeasureOp where+    eq2 x y = maybe False (const True) (jmEq2 x y)++instance Eq1 (MeasureOp typs) where+    eq1 = eq2++instance Eq (MeasureOp typs a) where -- This one can be derived+    (==) = eq1+++----------------------------------------------------------------+----------------------------------------------------------------+-- N.B., the precedence of (:$) must be lower than (:*).+-- N.B., if these are changed, then be sure to update the Show instances+infix  4 :$ -- Chosen to be at the same precedence as (<$>) rather than ($)+infixr 5 :* -- Chosen to match (:)+++-- | The constructor of a @(':$')@ node in the 'Term'. Each of these+-- constructors denotes a \"normal\/standard\/basic\" syntactic+-- form (i.e., a generalized quantifier). In the literature, these+-- syntactic forms are sometimes called \"operators\", but we avoid+-- calling them that so as not to introduce confusion vs 'PrimOp'+-- etc. Instead we use the term \"operator\" to refer to any primitive+-- function or constant; that is, non-binding syntactic forms. Also+-- in the literature, the 'SCon' type itself is usually called the+-- \"signature\" of the term language. However, we avoid calling+-- it that since our 'Term' has constructors other than just @(:$)@,+-- so 'SCon' does not give a complete signature for our terms.+--+-- The main reason for breaking this type out and using it in+-- conjunction with @(':$')@ and 'SArgs' is so that we can easily+-- pattern match on /fully saturated/ nodes. For example, we want+-- to be able to match @MeasureOp_ Uniform :$ lo :* hi :* End@+-- without needing to deal with 'App_' nodes nor 'viewABT'.+data SCon :: [([Hakaru], Hakaru)] -> Hakaru -> * where+    -- BUG: haddock doesn't like annotations on GADT constructors+    -- <https://github.com/hakaru-dev/hakaru/issues/6>++    -- -- Standard lambda calculus stuff+    Lam_ :: SCon '[ '( '[ a ], b ) ] (a ':-> b)+    App_ :: SCon '[ LC (a ':-> b ), LC a ] b+    Let_ :: SCon '[ LC a, '( '[ a ], b ) ] b+    -- TODO: a general \"@letrec*@\" version of let-binding so we can have mutual recursion+    --+    -- TODO: if we decide to add arbitrary fixedpoints back in, we+    -- should probably prefer only recursive-functions:+    -- `SCon '[ '( '[ a ':-> b, a ], a ':-> b ) ] (a ':-> b)`+    -- over than the previous recursive-everything:+    -- `SCon '[ '( '[ a ], a ) ] a`+    -- Or, if we really want to guarantee soundness, then we should+    -- only have the inductive principles for each HData.++    -- -- Type munging+    CoerceTo_   :: !(Coercion a b) -> SCon '[ LC a ] b+    UnsafeFrom_ :: !(Coercion a b) -> SCon '[ LC b ] a+    -- TODO: add something like @SafeFrom_ :: Coercion a b -> abt b -> Term abt ('HMaybe a)@ so we can capture the safety of patterns like @if_ (0 <= x) (let x_ = unsafeFrom signed x in...) (...)@ Of course, since we're just going to do case analysis on the result; why not make it a binding form directly?+    -- TODO: we'll probably want some more general thing to capture these sorts of patterns. For example, in the default implementation of Uniform we see: @if_ (lo < x && x < hi) (... unsafeFrom_ signed (hi - lo) ...) (...)@++    -- HACK: we must add the constraints that 'LCs' and 'UnLCs' are inverses, so that we have those in scope when doing case analysis (e.g., in TypeCheck.hs).+    -- As for this file itself, we can get it to typecheck by using 'UnLCs' in the argument rather than 'LCs' in the result; trying to do things the other way results in type inference issues in the typeclass instances for 'SCon'+    PrimOp_+        :: (typs ~ UnLCs args, args ~ LCs typs)+        => !(PrimOp typs a) -> SCon args a+    ArrayOp_+        :: (typs ~ UnLCs args, args ~ LCs typs)+        => !(ArrayOp typs a) -> SCon args a+    MeasureOp_+        :: (typs ~ UnLCs args, args ~ LCs typs)+        => !(MeasureOp typs a) -> SCon args ('HMeasure a)++    Dirac :: SCon '[ LC a ] ('HMeasure a)++    MBind :: SCon+        '[ LC ('HMeasure a)+        ,  '( '[ a ], 'HMeasure b)+        ] ('HMeasure b)++    -- TODO: unify Plate and Chain as @sequence@ a~la traversable?+    Plate :: SCon +        '[ LC 'HNat+        , '( '[ 'HNat ], 'HMeasure a)+        ] ('HMeasure ('HArray a))+++    -- TODO: if we swap the order of arguments to 'Chain', we could+    -- change the functional argument to be a binding form in order+    -- to avoid the need for lambdas. It'd no longer be trivial to+    -- see 'Chain' as an instance of @sequence@, but might be worth+    -- it... Of course, we also need to handle the fact that it's+    -- an array of transition functions; i.e., we could do:+    -- > chain n s0 $ \i s -> do {...}+    Chain :: SCon+        '[ LC 'HNat, LC s+        , '( '[ s ],  'HMeasure (HPair a s))+        ] ('HMeasure (HPair ('HArray a) s))+++    -- -- Continuous and discrete integration.+    -- TODO: make Integrate and Summate polymorphic, so that if the+    -- two inputs are HProb then we know the function must be over+    -- HProb\/HNat too. More generally, if the first input is HProb+    -- (since the second input is assumed to be greater than the+    -- first); though that would be a bit ugly IMO.+    Integrate+        :: SCon '[ LC 'HReal, LC 'HReal, '( '[ 'HReal ], 'HProb) ] 'HProb+    -- TODO: the high and low bounds *should* be HInt. The only reason we use HReal is so that we can have infinite summations. Once we figure out a way to handle infinite bounds here, we can make the switch++    Summate+        :: HDiscrete a+        -> HSemiring b+        -> SCon '[ LC a, LC a, '( '[ a ], b) ] b++    Product+        :: HDiscrete a+        -> HSemiring b+        -> SCon '[ LC a, LC a, '( '[ a ], b) ] b++    -- -- Internalized program transformations+    -- TODO: do these belong in their own place?+    --+    -- We generally want to evaluate these away at compile-time,+    -- but sometimes we may be stuck with a few unresolved things+    -- for open terms.++    -- TODO: did we want the singleton @a@ argument back?+    Expect :: SCon '[ LC ('HMeasure a), '( '[ a ], 'HProb) ] 'HProb++    -- TODO: implement a \"change of variables\" program transformation+    -- to map, say, @Lam_ x. blah (Expect x)@ into @Lam x'. blah x'@.+    -- Or, perhaps rather, transform it into @Lam_ x. App_ (Lam_ x'. blah x') (Expect x)@.++    -- TODO: add the four ops for disintegration+    Observe :: SCon '[ LC ('HMeasure a), LC a ] ('HMeasure a)+++deriving instance Eq   (SCon args a)+-- TODO: instance Read (SCon args a)+deriving instance Show (SCon args a)+++----------------------------------------------------------------+-- TODO: ideally we'd like to make SArgs totally flat, like tuples and arrays. Is there a way to do that with data families?+-- TODO: is there any good way to reuse 'List1' instead of defining 'SArgs' (aka @List2@)?++-- TODO: come up with a better name for 'End'+-- TODO: unify this with 'List1'? However, strictness differences...+--+-- | The arguments to a @(':$')@ node in the 'Term'; that is, a list+-- of ASTs, where the whole list is indexed by a (type-level) list+-- of the indices of each element.+data SArgs :: ([Hakaru] -> Hakaru -> *) -> [([Hakaru], Hakaru)] -> *+    where+    End :: SArgs abt '[]+    (:*) :: !(abt vars a)+        -> !(SArgs abt args)+        -> SArgs abt ( '(vars, a) ': args)++-- TODO: instance Read (SArgs abt args)++instance Show2 abt => Show1 (SArgs abt) where+    showsPrec1 _ End       = showString "End"+    showsPrec1 p (e :* es) =+        showParen (p > 5)+            ( showsPrec2 (p+1) e+            . showString " :* "+            . showsPrec1 (p+1) es+            )++instance Show2 abt => Show (SArgs abt args) where+    showsPrec = showsPrec1+    show      = show1++instance Eq2 abt => Eq1 (SArgs abt) where+    eq1 End       End       = True+    eq1 (x :* xs) (y :* ys) = eq2 x y && eq1 xs ys+    eq1 _         _         = False++instance Eq2 abt => Eq (SArgs abt args) where+    (==) = eq1++instance Functor21 SArgs where+    fmap21 f (e :* es) = f e :* fmap21 f es+    fmap21 _ End       = End++instance Foldable21 SArgs where+    foldMap21 f (e :* es) = f e `mappend` foldMap21 f es+    foldMap21 _ End       = mempty++instance Traversable21 SArgs where+    traverse21 f (e :* es) = (:*) <$> f e <*> traverse21 f es+    traverse21 _ End       = pure End+++----------------------------------------------------------------+-- | The generating functor for Hakaru ASTs. This type is given in+-- open-recursive form, where the first type argument gives the+-- recursive form. The recursive form @abt@ does not have exactly+-- the same kind as @Term abt@ because every 'Term' represents a+-- locally-closed term whereas the underlying @abt@ may bind some+-- variables.+data Term :: ([Hakaru] -> Hakaru -> *) -> Hakaru -> * where+    -- BUG: haddock doesn't like annotations on GADT constructors+    -- <https://github.com/hakaru-dev/hakaru/issues/6>++    -- Simple syntactic forms (i.e., generalized quantifiers)+    (:$) :: !(SCon args a) -> !(SArgs abt args) -> Term abt a++    -- N-ary operators+    NaryOp_ :: !(NaryOp a) -> !(Seq (abt '[] a)) -> Term abt a++    -- TODO: 'Literal_', 'Empty_', 'Array_', and 'Datum_' are generalized quantifiers (to the same extent that 'Ann_', 'CoerceTo_', and 'UnsafeFrom_' are). Should we move them into 'SCon' just for the sake of minimizing how much lives in 'Term'? Or are they unique enough to be worth keeping here?++    -- Literal\/Constant values+    Literal_ :: !(Literal a) -> Term abt a++    -- These two constructors are here rather than in 'ArrayOp' because 'Array_' is a binding form; though it also means they're together with the other intro forms like 'Literal_' and 'Datum_'.+    --+    -- TODO: should we add a @Sing a@ argument to avoid ambiguity of 'Empty_'?+    Empty_ :: !(Sing ('HArray a)) -> Term abt ('HArray a)+    Array_+        :: !(abt '[] 'HNat)+        -> !(abt '[ 'HNat ] a)+        -> Term abt ('HArray a)++    -- -- User-defined data types+    -- BUG: even though the 'Datum' type has a single constructor, we get a warning about not being able to UNPACK it in 'Datum_'... wtf?+    --+    -- A data constructor applied to some expressions. N.B., this+    -- definition only accounts for data constructors which are+    -- fully saturated. Unsaturated constructors will need to be+    -- eta-expanded.+    Datum_ :: !(Datum (abt '[]) (HData' t)) -> Term abt (HData' t)++    -- Generic case-analysis (via ABTs and Structural Focalization).+    Case_ :: !(abt '[] a) -> [Branch a abt b] -> Term abt b++    -- Linear combinations of measures.+    Superpose_+        :: L.NonEmpty (abt '[] 'HProb, abt '[] ('HMeasure a))+        -> Term abt ('HMeasure a)++    Reject_ :: !(Sing ('HMeasure a)) -> Term abt ('HMeasure a)++----------------------------------------------------------------+-- N.B., having a @singTerm :: Term abt a -> Sing a@ doesn't make+-- sense: That's what 'inferType' is for, but not all terms can be+-- inferred; some must be checked... Similarly, we can't derive+-- Read, since that's what typechecking is all about.+++-- | A newtype of @abt '[]@, because sometimes we need this in order+-- to give instances for things. In particular, this is often used+-- to derive the obvious @Foo1 (abt '[])@ instance from an underlying+-- @Foo2 abt@ instance. The primary motivating example is to give+-- the 'Datum_' branch of the @Show1 (Term abt)@ instance.+newtype LC_ (abt :: [Hakaru] -> Hakaru -> *) (a :: Hakaru) =+    LC_ { unLC_ :: abt '[] a }++instance Show2 abt => Show1 (LC_ abt) where+    showsPrec1 p = showsPrec2 p . unLC_+    show1        = show2        . unLC_++-- Alas, these two instances require importing ABT.hs+-- HACK: these instances require -XUndecidableInstances+instance ABT Term abt => Coerce (LC_ abt) where+    coerceTo   CNil e       = e+    coerceTo   c    (LC_ e) = LC_ (syn (CoerceTo_ c :$ e :* End))++    coerceFrom CNil e       = e+    coerceFrom c    (LC_ e) = LC_ (syn (UnsafeFrom_ c :$ e :* End))++instance ABT Term abt => Coerce (Term abt) where+    coerceTo   CNil e = e+    coerceTo   c    e = CoerceTo_ c :$ syn e :* End++    coerceFrom CNil e = e+    coerceFrom c    e = UnsafeFrom_ c :$ syn e :* End++instance Show2 abt => Show1 (Term abt) where+    showsPrec1 p t =+        case t of+        o :$ es ->+            showParen (p > 4)+                ( showsPrec  (p+1) o+                . showString " :$ "+                . showsPrec1 (p+1) es+                )+        NaryOp_ o es ->+            showParen (p > 9)+                ( showString "NaryOp_ "+                . showsPrec  11 o+                . showString " "+                . showParen True+                    ( showString "Seq.fromList "+                    . showList2 (F.toList es)+                    )+                )+        Literal_ v   -> showParen_0   p "Literal_" v+        Empty_ _     -> showString      "Empty_"+        Array_ e1 e2 -> showParen_22  p "Array_" e1 e2+        Datum_ d     -> showParen_1   p "Datum_" (fmap11 LC_ d)+        Case_  e bs  ->+            showParen (p > 9)+                ( showString "Case_ "+                . showsPrec2 11 e+                . showString " "+                . showList1 bs+                )+        Superpose_ pes ->+            showParen (p > 9)+                ( showString "Superpose_ "+                . showListWith+                    (\(e1,e2) -> showTuple [shows2 e1, shows2 e2])+                    (L.toList pes)+                )+        Reject_ _     -> showString      "Reject_"++instance Show2 abt => Show (Term abt a) where+    showsPrec = showsPrec1+    show      = show1+++----------------------------------------------------------------+instance Functor21 Term where+    fmap21 f (o :$ es)          = o :$ fmap21 f es+    fmap21 f (NaryOp_    o  es) = NaryOp_    o (fmap f es)+    fmap21 _ (Literal_   v)     = Literal_   v+    fmap21 _ (Empty_ t)         = Empty_ t+    fmap21 f (Array_     e1 e2) = Array_     (f e1) (f e2)+    fmap21 f (Datum_     d)     = Datum_     (fmap11 f d)+    fmap21 f (Case_      e  bs) = Case_      (f e)  (map (fmap21 f) bs)+    fmap21 f (Superpose_ pes)   = Superpose_ (L.map (f *** f) pes)+    fmap21 _ (Reject_ t)        = Reject_ t+++----------------------------------------------------------------+instance Foldable21 Term where+    foldMap21 f (_ :$ es)          = foldMap21 f es+    foldMap21 f (NaryOp_    _  es) = F.foldMap f es+    foldMap21 _ (Literal_   _)     = mempty+    foldMap21 _ (Empty_     _)     = mempty+    foldMap21 f (Array_     e1 e2) = f e1 `mappend` f e2+    foldMap21 f (Datum_     d)     = foldMap11 f d+    foldMap21 f (Case_      e  bs) = f e  `mappend` F.foldMap (foldMap21 f) bs+    foldMap21 f (Superpose_ pes)   = foldMapPairs f pes+    foldMap21 _ (Reject_    _)     = mempty++foldMapPairs+    :: (Monoid m, F.Foldable f)+    => (forall h i. abt h i -> m)+    -> f (abt xs a, abt ys b)+    -> m+foldMapPairs f = F.foldMap $ \(e1,e2) -> f e1 `mappend` f e2+++----------------------------------------------------------------+instance Traversable21 Term where+    traverse21 f (o :$ es)          = (o :$) <$> traverse21 f es+    traverse21 f (NaryOp_    o  es) = NaryOp_  o <$> traverse f es+    traverse21 _ (Literal_   v)     = pure $ Literal_ v+    traverse21 _ (Empty_     typ)   = pure $ Empty_   typ+    traverse21 f (Array_     e1 e2) = Array_ <$> f e1 <*> f e2+    traverse21 f (Datum_     d)     = Datum_ <$> traverse11 f d+    traverse21 f (Case_      e  bs) = Case_  <$> f e <*> traverse (traverse21 f) bs+    traverse21 f (Superpose_ pes)   = Superpose_ <$> traversePairs f pes+    traverse21 _ (Reject_    typ)   = pure $ Reject_  typ++traversePairs+    :: (Applicative f, Traversable t)+    => (forall h i. abt1 h i -> f (abt2 h i))+    -> t (abt1 xs a, abt1 ys b)+    -> f (t (abt2 xs a, abt2 ys b))+traversePairs f = traverse $ \(x,y) -> (,) <$> f x <*> f y++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Syntax/AST/Eq.hs view
@@ -0,0 +1,494 @@+{-# LANGUAGE CPP+           , DataKinds+           , GADTs+           , TypeOperators+           , PolyKinds+           , FlexibleContexts+           , ScopedTypeVariables+           , UndecidableInstances+           #-}++-- TODO: all the instances here are orphans. To ensure that we don't+-- have issues about orphan instances, we should give them all+-- newtypes and only provide the instance for those newtypes!+-- (and\/or: for the various op types, it's okay to move them to+-- AST.hs to avoid orphanage. It's just the instances for 'Term'+-- itself which are morally suspect outside of testing.)+{-# OPTIONS_GHC -Wall -fwarn-tabs -fno-warn-orphans #-}+----------------------------------------------------------------+--                                                    2016.05.24+-- |+-- Module      :  Language.Hakaru.Syntax.ABT.Eq+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- Warning: The following module is for testing purposes only. Using+-- the 'JmEq1' instance for 'Term' is inefficient and should not+-- be done accidentally. To implement that (orphan) instance we+-- also provide the following (orphan) instances:+--+-- > SArgs      : JmEq1+-- > Term       : JmEq1, Eq1, Eq+-- > TrivialABT : JmEq2, JmEq1, Eq2, Eq1, Eq+--+-- TODO: because this is only for testing, everything else should+-- move to the @Tests@ directory.+----------------------------------------------------------------+module Language.Hakaru.Syntax.AST.Eq where++import Language.Hakaru.Types.DataKind+import Language.Hakaru.Types.Sing+import Language.Hakaru.Types.Coercion+import Language.Hakaru.Types.HClasses+import Language.Hakaru.Syntax.IClasses+import Language.Hakaru.Syntax.ABT+import Language.Hakaru.Syntax.AST+import Language.Hakaru.Syntax.Datum+import Language.Hakaru.Syntax.TypeOf++import Control.Monad.Reader++import qualified Data.Foldable      as F+import qualified Data.List.NonEmpty as L+import qualified Data.Sequence      as S+import qualified Data.Traversable   as T++#if __GLASGOW_HASKELL__ < 710+import           Data.Functor ((<$>))+import           Data.Traversable+#endif+++import Data.Maybe+-- import Data.Number.Nat++import Unsafe.Coerce++---------------------------------------------------------------------+-- | This function performs 'jmEq' on a @(:$)@ node of the AST.+-- It's necessary to break it out like this since we can't just+-- give a 'JmEq1' instance for 'SCon' due to polymorphism issues+-- (e.g., we can't just say that 'Lam_' is John Major equal to+-- 'Lam_', since they may be at different types). However, once the+-- 'SArgs' associated with the 'SCon' is given, that resolves the+-- polymorphism.+jmEq_S+    :: (ABT Term abt, JmEq2 abt)+    => SCon args  a  -> SArgs abt args+    -> SCon args' a' -> SArgs abt args'+    -> Maybe (TypeEq a a', TypeEq args args')+jmEq_S Lam_      es Lam_       es' =+    jmEq1 es es' >>= \Refl -> Just (Refl, Refl)+jmEq_S App_      es App_       es' =+    jmEq1 es es' >>= \Refl -> Just (Refl, Refl)+jmEq_S Let_      es Let_       es' =+    jmEq1 es es' >>= \Refl -> Just (Refl, Refl)+jmEq_S (CoerceTo_ c) (es :* End) (CoerceTo_ c') (es' :* End) = do+    (Refl, Refl) <- jmEq2 es es'+    let t1 = coerceTo c  (typeOf es)+    let t2 = coerceTo c' (typeOf es')+    Refl <- jmEq1 t1 t2+    return (Refl, Refl)+jmEq_S (UnsafeFrom_ c) (es :* End) (UnsafeFrom_ c') (es' :* End) = do+    (Refl, Refl) <- jmEq2 es es'+    let t1 = coerceFrom c  (typeOf es)+    let t2 = coerceFrom c' (typeOf es')+    Refl <- jmEq1 t1 t2+    return (Refl, Refl)+jmEq_S (PrimOp_ op) es (PrimOp_ op') es' = do+    Refl <- jmEq1 es es'+    (Refl, Refl) <- jmEq2 op op'+    return (Refl, Refl)+jmEq_S (ArrayOp_ op) es (ArrayOp_ op') es' = do+    Refl <- jmEq1 es es'+    (Refl, Refl) <- jmEq2 op op'+    return (Refl, Refl)+jmEq_S (MeasureOp_ op) es (MeasureOp_ op') es' = do+    Refl <- jmEq1 es es'+    (Refl, Refl) <- jmEq2 op op'+    return (Refl, Refl)+jmEq_S Dirac     es Dirac      es' =+    jmEq1 es es' >>= \Refl -> Just (Refl, Refl)+jmEq_S MBind     es MBind      es' =+    jmEq1 es es' >>= \Refl -> Just (Refl, Refl)+jmEq_S Integrate es Integrate  es' =+    jmEq1 es es' >>= \Refl -> Just (Refl, Refl)+jmEq_S (Summate h1 h2) es (Summate h1' h2') es' = do+    Refl <- jmEq1 (sing_HDiscrete h1) (sing_HDiscrete h1')+    Refl <- jmEq1 (sing_HSemiring h2) (sing_HSemiring h2')+    Refl <- jmEq1 es es'+    Just (Refl, Refl)+jmEq_S Expect    es Expect     es' =+    jmEq1 es es' >>= \Refl -> Just (Refl, Refl)+jmEq_S _         _  _          _   = Nothing+++-- TODO: Handle jmEq2 of pat and pat'+jmEq_Branch+    :: (ABT Term abt, JmEq2 abt)+    => [(Branch a abt b, Branch a abt b')]+    -> Maybe (TypeEq b b')+jmEq_Branch []                                  = Nothing+jmEq_Branch [(Branch pat e, Branch pat' e')]    = do+    (Refl, Refl) <- jmEq2 e e'+    return Refl+jmEq_Branch ((Branch pat e, Branch pat' e'):es) = do+    (Refl, Refl) <- jmEq2 e e'+    jmEq_Branch es++instance JmEq2 abt => JmEq1 (SArgs abt) where+    jmEq1 End       End       = Just Refl+    jmEq1 (x :* xs) (y :* ys) =+        jmEq2 x  y  >>= \(Refl, Refl) ->+        jmEq1 xs ys >>= \Refl ->+        Just Refl+    jmEq1 _         _         = Nothing+++instance (ABT Term abt, JmEq2 abt) => JmEq1 (Term abt) where+    jmEq1 (o :$ es) (o' :$ es') = do+        (Refl, Refl) <- jmEq_S o es o' es'+        return Refl+    jmEq1 (NaryOp_ o es) (NaryOp_ o' es') = do+        Refl <- jmEq1 o o'+        () <- all_jmEq2 es es'+        return Refl+    jmEq1 (Literal_ v)  (Literal_ w)   = jmEq1 v w+    jmEq1 (Empty_ a)    (Empty_ b)     = jmEq1 a b+    jmEq1 (Array_ i f)  (Array_ j g)   = do+        (Refl, Refl) <- jmEq2 i j+        (Refl, Refl) <- jmEq2 f g+        Just Refl+    jmEq1 (Datum_ (Datum hint _ _)) (Datum_ (Datum hint' _ _))+        -- BUG: We need to compare structurally rather than using the hint+        | hint == hint' = unsafeCoerce (Just Refl)+        | otherwise     = Nothing+    jmEq1 (Case_  a bs) (Case_  a' bs')      = do+        (Refl, Refl) <- jmEq2 a a'+        jmEq_Branch (zip bs bs')+    jmEq1 (Superpose_ pms) (Superpose_ pms') = do+      (Refl,Refl) L.:| _ <- T.sequence $ fmap jmEq_Tuple (L.zip pms pms')+      return Refl+    jmEq1 _              _              = Nothing+++all_jmEq2+    :: (ABT Term abt, JmEq2 abt)+    => S.Seq (abt '[] a)+    -> S.Seq (abt '[] a)+    -> Maybe ()+all_jmEq2 xs ys =+    let eq x y = isJust (jmEq2 x y)+    in if F.and (S.zipWith eq xs ys) then Just () else Nothing+++jmEq_Tuple :: (ABT Term abt, JmEq2 abt)+           => ((abt '[] a , abt '[] b), +               (abt '[] a', abt '[] b'))+           -> Maybe (TypeEq a a', TypeEq b b')+jmEq_Tuple ((a,b), (a',b')) = do+  a'' <- jmEq2 a a' >>= (\(Refl, Refl) -> Just Refl)+  b'' <- jmEq2 b b' >>= (\(Refl, Refl) -> Just Refl)+  return (a'', b'')+++-- TODO: a more general function of type:+--   (JmEq2 abt) => Term abt a -> Term abt b -> Maybe (Sing a, TypeEq a b)+-- This can then be used to define typeOf and instance JmEq2 Term++instance (ABT Term abt, JmEq2 abt) => Eq1 (Term abt) where+    eq1 x y = isJust (jmEq1 x y)++instance (ABT Term abt, JmEq2 abt) => Eq (Term abt a) where+    (==) = eq1++instance ( Show1 (Sing :: k -> *)+         , JmEq1 (Sing :: k -> *)+         , JmEq1 (syn (TrivialABT syn))+         , Foldable21 syn+         ) => JmEq2 (TrivialABT (syn :: ([k] -> k -> *) -> k -> *))+    where+    jmEq2 x y =+        case (viewABT x, viewABT y) of+        (Syn t1, Syn t2) ->+            jmEq1 t1 t2 >>= \Refl -> Just (Refl, Refl) +        (Var (Variable _ _ t1), Var (Variable _ _ t2)) ->+            jmEq1 t1 t2 >>= \Refl -> Just (Refl, Refl)+        (Bind (Variable _ _ x1) v1, Bind (Variable _ _ x2) v2) -> do+            Refl <- jmEq1 x1 x2+            (Refl,Refl) <- jmEq2 (unviewABT v1) (unviewABT v2)+            return (Refl, Refl)+        _ -> Nothing++instance ( Show1 (Sing :: k -> *)+         , JmEq1 (Sing :: k -> *)+         , JmEq1 (syn (TrivialABT syn))+         , Foldable21 syn+         ) => JmEq1 (TrivialABT (syn :: ([k] -> k -> *) -> k -> *) xs)+    where+    jmEq1 x y = jmEq2 x y >>= \(Refl, Refl) -> Just Refl++instance ( Show1 (Sing :: k ->  *)+         , JmEq1 (Sing :: k -> *)+         , Foldable21 syn+         , JmEq1 (syn (TrivialABT syn))+         ) => Eq2 (TrivialABT (syn :: ([k] -> k -> *) -> k -> *))+    where+    eq2 x y = isJust (jmEq2 x y)++instance ( Show1 (Sing :: k ->  *)+         , JmEq1 (Sing :: k -> *)+         , Foldable21 syn+         , JmEq1 (syn (TrivialABT syn))+         ) => Eq1 (TrivialABT (syn :: ([k] -> k -> *) -> k -> *) xs)+    where+    eq1 = eq2++instance ( Show1 (Sing :: k ->  *)+         , JmEq1 (Sing :: k -> *)+         , Foldable21 syn+         , JmEq1 (syn (TrivialABT syn))+         ) => Eq (TrivialABT (syn :: ([k] -> k -> *) -> k -> *) xs a)+    where+    (==) = eq1+++type Varmap = Assocs (Variable :: Hakaru -> *)++void_jmEq1+    :: Sing (a :: Hakaru)+    -> Sing (b :: Hakaru)+    -> ReaderT Varmap Maybe ()+void_jmEq1 x y = lift (jmEq1 x y) >> return ()++void_varEq+    :: Variable (a :: Hakaru)+    -> Variable (b :: Hakaru)+    -> ReaderT Varmap Maybe ()   +void_varEq x y = lift (varEq x y) >> return ()++try_bool :: Bool -> ReaderT Varmap Maybe ()+try_bool b = lift $ if b then Just () else Nothing++alphaEq+    :: forall abt a+    .  (ABT Term abt)+    => abt '[] a+    -> abt '[] a+    -> Bool+alphaEq e1 e2 =+    maybe False (const True)+        $ runReaderT (go (viewABT e1) (viewABT e2)) emptyAssocs+    where+    -- Don't compare @x@ to @y@ directly; instead,+    -- look up whatever @x@ renames to (i.e., @y'@)+    -- and then see whether that is equal to @y@.+    go  :: forall xs1 xs2 a+        .  View (Term abt) xs1 a+        -> View (Term abt) xs2 a+        -> ReaderT Varmap Maybe ()+    go (Var x) (Var y) = do+        s <- ask+        case lookupAssoc x s of+            Nothing -> void_varEq x  y -- free variables+            Just y' -> void_varEq y' y++    -- remember that @x@ renames to @y@ and recurse+    go (Bind x e1) (Bind y e2) = do+        Refl <- lift $ jmEq1 (varType x) (varType y)+        local (insertAssoc (Assoc x y)) (go e1 e2)++    -- perform the core comparison for syntactic equality+    go (Syn t1) (Syn t2) = termEq t1 t2++    -- if the views don't match, then clearly they are not equal.+    go _ _ = lift Nothing++    termEq :: forall a+        .  Term abt a+        -> Term abt a+        -> ReaderT Varmap Maybe ()+    termEq e1 e2 =+        case (e1, e2) of+        (o1 :$ es1, o2 :$ es2)             -> sConEq o1 es1 o2 es2+        (NaryOp_ op1 es1, NaryOp_ op2 es2) -> do+            try_bool (op1 == op2)+            F.sequence_ $ S.zipWith go (viewABT <$> es1) (viewABT <$> es2)+        (Literal_ x, Literal_ y)           -> try_bool (x == y)+        (Empty_ x, Empty_ y)               -> void_jmEq1 x y+        (Datum_ d1, Datum_ d2)             -> datumEq d1 d2+        (Array_ n1 e1, Array_ n2 e2)       -> do+            go (viewABT n1) (viewABT n2)+            go (viewABT e1) (viewABT e2)+        (Case_ e1 bs1, Case_ e2 bs2)       -> do+            Refl <- lift $ jmEq1 (typeOf e1) (typeOf e2)+            go (viewABT e1) (viewABT e2)+            zipWithM_ sBranch bs1 bs2+        (Superpose_ pms1, Superpose_ pms2) ->+            F.sequence_ $ L.zipWith pairEq pms1 pms2+        (Reject_ x, Reject_ y)             -> void_jmEq1 x y+        (_, _)                             -> lift Nothing++    sArgsEq+        :: forall args+        .  SArgs abt args+        -> SArgs abt args+        -> ReaderT Varmap Maybe ()+    sArgsEq End         End         = return ()+    sArgsEq (e1 :* es1) (e2 :* es2) = do+        go (viewABT e1) (viewABT e2)+        sArgsEq es1 es2+    sArgsEq _ _ = lift Nothing++    sConEq+        :: forall a args1 args2+        .  SCon  args1 a+        -> SArgs abt args1+        -> SCon args2 a+        -> SArgs abt args2+        -> ReaderT Varmap Maybe ()+    sConEq Lam_   e1+           Lam_   e2 = sArgsEq e1 e2++    sConEq App_   (e1  :* e2  :* End)+           App_   (e1' :* e2' :* End) = do+        Refl <- lift $ jmEq1 (typeOf e2) (typeOf e2')+        go (viewABT e1) (viewABT e1')+        go (viewABT e2) (viewABT e2')++    sConEq Let_   (e1  :* e2  :* End)+           Let_   (e1' :* e2' :* End) = do+        Refl <- lift $ jmEq1 (typeOf e1) (typeOf e1')+        go (viewABT e1) (viewABT e1')+        go (viewABT e2) (viewABT e2')++    sConEq (CoerceTo_ _) (e1 :* End)+           (CoerceTo_ _) (e2 :* End) =+        void_jmEq1 (typeOf e1) (typeOf e2)++    sConEq (UnsafeFrom_ _) (e1 :* End)+           (UnsafeFrom_ _) (e2 :* End) =+        void_jmEq1 (typeOf e1) (typeOf e2)++    sConEq (PrimOp_ o1) es1+           (PrimOp_ o2) es2    = primOpEq o1 es1 o2 es2++    sConEq (ArrayOp_ o1) es1+           (ArrayOp_ o2) es2   = arrayOpEq o1 es1 o2 es2++    sConEq (MeasureOp_ o1) es1+           (MeasureOp_ o2) es2 = measureOpEq o1 es1 o2 es2++    sConEq Dirac e1+           Dirac e2            = sArgsEq e1 e2++    sConEq MBind (e1  :* e2  :* End)+           MBind (e1' :* e2' :* End) = do+        Refl <- lift $ jmEq1 (typeOf e1) (typeOf e1')+        go (viewABT e1) (viewABT e1')+        go (viewABT e2) (viewABT e2')++    sConEq Plate     e1 Plate     e2    = sArgsEq e1 e2+    sConEq Chain     e1 Chain     e2    = sArgsEq e1 e2+    sConEq Integrate e1 Integrate e2    = sArgsEq e1 e2++    sConEq (Summate h1 h2) e1 (Summate h1' h2') e2 = do+        Refl <- lift $ jmEq1 (sing_HDiscrete h1) (sing_HDiscrete h1')+        Refl <- lift $ jmEq1 (sing_HSemiring h2) (sing_HSemiring h2')+        sArgsEq e1 e2++    sConEq Expect (e1  :* e2  :* End)+           Expect (e1' :* e2' :* End) = do+        Refl <- lift $ jmEq1 (typeOf e1) (typeOf e1')+        go (viewABT e1) (viewABT e1')+        go (viewABT e2) (viewABT e2')++    sConEq _ _ _ _ = lift Nothing+++    primOpEq+        :: forall a typs1 typs2 args1 args2+        .  (typs1 ~ UnLCs args1, args1 ~ LCs typs1,+            typs2 ~ UnLCs args2, args2 ~ LCs typs2)+        => PrimOp typs1 a -> SArgs abt args1+        -> PrimOp typs2 a -> SArgs abt args2+        -> ReaderT Varmap Maybe ()+    primOpEq p1 e1 p2 e2 = do+        (Refl, Refl) <- lift $ jmEq2 p1 p2+        sArgsEq e1 e2++    arrayOpEq+        :: forall a typs1 typs2 args1 args2+        .  (typs1 ~ UnLCs args1, args1 ~ LCs typs1,+            typs2 ~ UnLCs args2, args2 ~ LCs typs2)+        => ArrayOp typs1 a -> SArgs abt args1+        -> ArrayOp typs2 a -> SArgs abt args2+        -> ReaderT Varmap Maybe ()+    arrayOpEq p1 e1 p2 e2 = do+        (Refl, Refl) <- lift $ jmEq2 p1 p2+        sArgsEq e1 e2++    measureOpEq+        :: forall a typs1 typs2 args1 args2+        . (typs1 ~ UnLCs args1, args1 ~ LCs typs1,+            typs2 ~ UnLCs args2, args2 ~ LCs typs2)+        => MeasureOp typs1 a -> SArgs abt args1+        -> MeasureOp typs2 a -> SArgs abt args2+        -> ReaderT Varmap Maybe ()+    measureOpEq m1 e1 m2 e2 = do+        (Refl,Refl) <- lift $ jmEq2 m1 m2+        sArgsEq e1 e2++    datumEq :: forall a+        .  Datum (abt '[]) a+        -> Datum (abt '[]) a+        -> ReaderT Varmap Maybe ()+    datumEq (Datum _ _ d1) (Datum _ _ d2) = datumCodeEq d1 d2++    datumCodeEq+        :: forall xss a+        .  DatumCode xss (abt '[]) a+        -> DatumCode xss (abt '[]) a+        -> ReaderT Varmap Maybe ()+    datumCodeEq (Inr c) (Inr d) = datumCodeEq c d+    datumCodeEq (Inl c) (Inl d) = datumStructEq c d+    datumCodeEq _       _       = lift Nothing++    datumStructEq+        :: forall xs a+        .  DatumStruct xs (abt '[]) a+        -> DatumStruct xs (abt '[]) a+        -> ReaderT Varmap Maybe ()+    datumStructEq (Et c1 c2) (Et d1 d2) = do+        datumFunEq c1 d1+        datumStructEq c2 d2+    datumStructEq Done       Done       = return ()+    datumStructEq _          _          = lift Nothing+    +    datumFunEq+        :: forall x a+        .  DatumFun x (abt '[]) a+        -> DatumFun x (abt '[]) a+        -> ReaderT Varmap Maybe ()+    datumFunEq (Konst e) (Konst f) = go (viewABT e) (viewABT f) +    datumFunEq (Ident e) (Ident f) = go (viewABT e) (viewABT f) +    datumFunEq _          _        = lift Nothing+    +    pairEq+        :: forall a b+        .  (abt '[] a, abt '[] b)+        -> (abt '[] a, abt '[] b)+        -> ReaderT Varmap Maybe ()+    pairEq (x1, y1) (x2, y2) = do+        go (viewABT x1) (viewABT x2)+        go (viewABT y1) (viewABT y2)++    sBranch+        :: forall a b+        .  Branch a abt b+        -> Branch a abt b+        -> ReaderT Varmap Maybe ()+    sBranch (Branch _ e1) (Branch _ e2) = go (viewABT e1) (viewABT e2)
+ haskell/Language/Hakaru/Syntax/AST/Sing.hs view
@@ -0,0 +1,134 @@+{-# LANGUAGE CPP, GADTs #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2015.12.19+-- |+-- Module      :  Language.Hakaru.Syntax.AST.Sing+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- Factored out from "Language.Hakaru.Syntax.AST".+--+-- TODO: if we're not going to have this in "Language.Hakaru.Syntax.AST", then we should rename it to @Language.Hakaru.Syntax.AST.Sing@ or the like.+----------------------------------------------------------------+module Language.Hakaru.Syntax.AST.Sing+    ( sing_NaryOp+    , sing_PrimOp+    , sing_ArrayOp+    , sing_MeasureOp+    , sing_Literal+    ) where++import Language.Hakaru.Syntax.IClasses+import Language.Hakaru.Types.HClasses+import Language.Hakaru.Types.Sing+import Language.Hakaru.Syntax.AST++----------------------------------------------------------------+----------------------------------------------------------------++-- N.B., we do case analysis so that we don't need the class constraint!+sing_Literal :: Literal a -> Sing a+sing_Literal (LNat  _) = sing+sing_Literal (LInt  _) = sing+sing_Literal (LProb _) = sing+sing_Literal (LReal _) = sing++-- TODO: we don't need to store the HOrd\/HSemiring values here,+-- we can recover them by typeclass, just like we use 'sing' to get+-- 'sBool' for the other ones...+sing_NaryOp :: NaryOp a -> Sing a+sing_NaryOp And            = sing+sing_NaryOp Or             = sing+sing_NaryOp Xor            = sing+sing_NaryOp Iff            = sing+sing_NaryOp (Min  theOrd)  = sing_HOrd      theOrd+sing_NaryOp (Max  theOrd)  = sing_HOrd      theOrd+sing_NaryOp (Sum  theSemi) = sing_HSemiring theSemi+sing_NaryOp (Prod theSemi) = sing_HSemiring theSemi++-- TODO: is there any way to define a @sing_List1@ like @sing@ for automating all these monomorphic cases?+sing_PrimOp :: PrimOp typs a -> (List1 Sing typs, Sing a)+sing_PrimOp Not          = (sing `Cons1` Nil1, sing)+sing_PrimOp Impl         = (sing `Cons1` sing `Cons1` Nil1, sing)+sing_PrimOp Diff         = (sing `Cons1` sing `Cons1` Nil1, sing)+sing_PrimOp Nand         = (sing `Cons1` sing `Cons1` Nil1, sing)+sing_PrimOp Nor          = (sing `Cons1` sing `Cons1` Nil1, sing)+sing_PrimOp Pi           = (Nil1, sing)+sing_PrimOp Sin          = (sing `Cons1` Nil1, sing)+sing_PrimOp Cos          = (sing `Cons1` Nil1, sing)+sing_PrimOp Tan          = (sing `Cons1` Nil1, sing)+sing_PrimOp Asin         = (sing `Cons1` Nil1, sing)+sing_PrimOp Acos         = (sing `Cons1` Nil1, sing)+sing_PrimOp Atan         = (sing `Cons1` Nil1, sing)+sing_PrimOp Sinh         = (sing `Cons1` Nil1, sing)+sing_PrimOp Cosh         = (sing `Cons1` Nil1, sing)+sing_PrimOp Tanh         = (sing `Cons1` Nil1, sing)+sing_PrimOp Asinh        = (sing `Cons1` Nil1, sing)+sing_PrimOp Acosh        = (sing `Cons1` Nil1, sing)+sing_PrimOp Atanh        = (sing `Cons1` Nil1, sing)+sing_PrimOp RealPow      = (sing `Cons1` sing `Cons1` Nil1, sing)+sing_PrimOp Exp          = (sing `Cons1` Nil1, sing)+sing_PrimOp Log          = (sing `Cons1` Nil1, sing)+sing_PrimOp (Infinity h) = (Nil1, sing_HIntegrable h)+sing_PrimOp GammaFunc    = (sing `Cons1` Nil1, sing)+sing_PrimOp BetaFunc     = (sing `Cons1` sing `Cons1` Nil1, sing)+-- Mere case analysis isn't enough for the rest of these, because+-- of the class constraints. We fix that by various helper functions+-- on explicit dictionary passing.+--+-- TODO: is there any way to automate building these from their+-- respective @a@ proofs?+sing_PrimOp (Equal theEq) =+    let a = sing_HEq theEq+    in  (a `Cons1` a `Cons1` Nil1, sBool)+sing_PrimOp (Less theOrd) =+    let a = sing_HOrd theOrd+    in  (a `Cons1` a `Cons1` Nil1, sBool)+sing_PrimOp (NatPow theSemi) =+    let a = sing_HSemiring theSemi+    in  (a `Cons1` SNat `Cons1` Nil1, a)+sing_PrimOp (Negate theRing) =+    let a = sing_HRing theRing+    in  (a `Cons1` Nil1, a)+sing_PrimOp (Abs theRing) =+    let a = sing_HRing theRing+        b = sing_NonNegative theRing+    in  (a `Cons1` Nil1, b)+sing_PrimOp (Signum theRing) =+    let a = sing_HRing theRing+    in  (a `Cons1` Nil1, a)+sing_PrimOp (Recip theFrac) =+    let a = sing_HFractional theFrac+    in  (a `Cons1` Nil1, a)+sing_PrimOp (NatRoot theRad) =+    let a = sing_HRadical theRad+    in  (a `Cons1` SNat `Cons1` Nil1, a)+sing_PrimOp (Erf theCont) =+    let a = sing_HContinuous theCont+    in  (a `Cons1` Nil1, a)+++sing_ArrayOp :: ArrayOp typs a -> (List1 Sing typs, Sing a)+sing_ArrayOp (Index  a) = (SArray a `Cons1` SNat `Cons1` Nil1, a)+sing_ArrayOp (Size   a) = (SArray a `Cons1` Nil1, SNat)+sing_ArrayOp (Reduce a) =+    ((a `SFun` a `SFun` a) `Cons1` a `Cons1` SArray a `Cons1` Nil1, a)+++sing_MeasureOp :: MeasureOp typs a -> (List1 Sing typs, Sing a)+sing_MeasureOp Lebesgue    = (Nil1, sing)+sing_MeasureOp Counting    = (Nil1, sing)+sing_MeasureOp Categorical = (sing `Cons1` Nil1, sing)+sing_MeasureOp Uniform     = (sing `Cons1` sing `Cons1` Nil1, sing)+sing_MeasureOp Normal      = (sing `Cons1` sing `Cons1` Nil1, sing)+sing_MeasureOp Poisson     = (sing `Cons1` Nil1, sing)+sing_MeasureOp Gamma       = (sing `Cons1` sing `Cons1` Nil1, sing)+sing_MeasureOp Beta        = (sing `Cons1` sing `Cons1` Nil1, sing)++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Syntax/AST/Transforms.hs view
@@ -0,0 +1,89 @@+{-# LANGUAGE FlexibleContexts+           , GADTs+           , Rank2Types+           , ScopedTypeVariables+           , DataKinds+           , TypeOperators+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+---------------------------------------------------------------+module Language.Hakaru.Syntax.AST.Transforms where++import qualified Data.Sequence as S++import Language.Hakaru.Syntax.ABT+import Language.Hakaru.Syntax.AST+import Language.Hakaru.Syntax.TypeOf+import Language.Hakaru.Syntax.IClasses+import Language.Hakaru.Types.DataKind++import Language.Hakaru.Expect       (expect)+import Language.Hakaru.Disintegrate (determine, observe)++underLam+    :: (ABT Term abt, Monad m)+    => (abt '[] b -> m (abt '[] b))+    -> abt '[] (a ':-> b)+    -> m (abt '[] (a ':-> b))+underLam f e = caseVarSyn e (return . var) $ \t ->+                   case t of+                   Lam_ :$ e1 :* End ->+                       caseBind e1 $ \x e1' -> do+                           e1'' <- f e1'+                           return . syn $+                                  Lam_  :$ (bind x e1'' :* End)++                   Let_ :$ e1 :* e2 :* End ->+                        case jmEq1 (typeOf e1) (typeOf e) of+                          Just Refl -> do+                               e1' <- underLam f e1+                               return . syn $+                                      Let_ :$ e1' :* e2 :* End+                          Nothing   -> caseBind e2 $ \x e2' -> do+                                         e2'' <- underLam f e2'+                                         return . syn $+                                                Let_ :$ e1 :* (bind x e2'') :* End++                   _ -> error "TODO: underLam"+++expandTransformations+    :: forall abt a+    . (ABT Term abt)+    => abt '[] a -> abt '[] a+expandTransformations =+    cataABT var bind alg+    where +    alg :: forall b. Term abt b -> abt '[] b+    alg t =+        case t of+        Expect  :$ e1 :* e2 :* End -> expect  e1 e2+        Observe :$ e1 :* e2 :* End ->+          case determine (observe e1 e2) of+          Just t' -> t'+          Nothing -> syn t+        _                         -> syn t+        +coalesce+  :: forall abt a+  .  (ABT Term abt)+  => abt '[] a+  -> abt '[] a+coalesce abt = caseVarSyn abt var onNaryOps+  where onNaryOps (NaryOp_ t es) = syn $ NaryOp_ t (coalesceNaryOp t es)+        onNaryOps term           = syn term++coalesceNaryOp+  :: ABT Term abt+  => NaryOp a+  -> S.Seq (abt '[] a)+  -> S.Seq (abt '[] a)+coalesceNaryOp typ args =+  do abt <- args+     case viewABT abt of+       Syn (NaryOp_ typ' args') ->+         if typ == typ'+         then coalesceNaryOp typ args'+         else return (coalesce abt)+       _ -> return abt
+ haskell/Language/Hakaru/Syntax/Datum.hs view
@@ -0,0 +1,797 @@+{-# LANGUAGE CPP+           , DataKinds+           , PolyKinds+           , GADTs+           , TypeOperators+           , TypeFamilies+           , ExistentialQuantification+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.05.24+-- |+-- Module      :  Language.Hakaru.Syntax.Datum+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- Haskell types and helpers for Hakaru's user-defined data types.+-- At present we only support regular-recursive polynomial data+-- types. Reduction of case analysis on data types is in+-- "Language.Hakaru.Syntax.Datum".+--+-- /Developers note:/ many of the 'JmEq1' instances in this file+-- don't actually work because of problems with matching existentially+-- quantified types in the basis cases. For now I've left the+-- partially-defined code in place, but turned it off with the+-- @__PARTIAL_DATUM_JMEQ__@ CPP macro. In the future we should+-- either (a) remove this unused code, or (b) if the instances are+-- truly necessary then we should add the 'Sing' arguments everywhere+-- to make things work :(+----------------------------------------------------------------+module Language.Hakaru.Syntax.Datum+    (+    -- * Data constructors+      Datum(..), datumHint, datumType+    , DatumCode(..)+    , DatumStruct(..)+    , DatumFun(..)+    -- ** Some smart constructors for the \"built-in\" datatypes+    , dTrue, dFalse+    , dUnit+    , dPair+    , dLeft, dRight+    , dNil, dCons+    , dNothing, dJust+    -- *** Variants which allow explicit type passing.+    , dPair_+    , dLeft_, dRight_+    , dNil_, dCons_+    , dNothing_, dJust_++    -- * Pattern constructors+    , Branch(..)+    , Pattern(..)+    , PDatumCode(..)+    , PDatumStruct(..)+    , PDatumFun(..)+    -- ** Some smart constructors for the \"built-in\" datatypes+    , pTrue, pFalse+    , pUnit+    , pPair+    , pLeft, pRight+    , pNil, pCons+    , pNothing, pJust+    -- ** Generalized branches+    , GBranch(..)+    ) where++import qualified Data.Text     as Text+import           Data.Text     (Text)+#if __GLASGOW_HASKELL__ < 710+import Data.Monoid             (Monoid(..))+import Control.Applicative+#endif+import qualified Data.Foldable    as F+import qualified Data.Traversable as T++import Language.Hakaru.Syntax.IClasses+import Language.Hakaru.Syntax.Variable (Variable(..))+-- TODO: make things polykinded so we can make our ABT implementation+-- independent of Hakaru's type system.+import Language.Hakaru.Types.DataKind+import Language.Hakaru.Types.Sing++----------------------------------------------------------------+----------------------------------------------------------------++#if __PARTIAL_DATUM_JMEQ__+cannotProve :: String -> a+cannotProve fun =+    error $ "Language.Hakaru.Syntax.Datum." ++ fun ++ ": Cannot prove Refl because of phantomness"+#endif+++-- TODO: change the kind to @(Hakaru -> *) -> HakaruCon -> *@ so+-- we can avoid the use of GADTs? Would that allow us to actually+-- UNPACK?+--+-- | A fully saturated data constructor, which recurses as @ast@.+-- We define this type as separate from 'DatumCode' for two reasons.+-- First is to capture the fact that the datum is \"complete\"+-- (i.e., is a well-formed constructor). The second is to have a+-- type which is indexed by its 'Hakaru' type, whereas 'DatumCode'+-- involves non-Hakaru types.+--+-- The first component is a hint for what the data constructor+-- should be called when pretty-printing, giving error messages,+-- etc. Like the hints for variable names, its value is not actually+-- used to decide which constructor is meant or which pattern+-- matches.+data Datum :: (Hakaru -> *) -> Hakaru -> * where+    Datum+        :: {-# UNPACK #-} !Text+        -> !(Sing (HData' t))+        -> !(DatumCode (Code t) ast (HData' t))+        -> Datum ast (HData' t)++datumHint :: Datum ast (HData' t) -> Text+datumHint (Datum hint _ _) = hint++datumType :: Datum ast (HData' t) -> Sing (HData' t)+datumType (Datum _ typ _) = typ++-- N.B., This doesn't require jmEq on 'DatumCode' nor on @ast@. The+-- jmEq on the singleton is sufficient.+instance Eq1 ast => JmEq1 (Datum ast) where+    jmEq1 (Datum _ typ1 d1) (Datum _ typ2 d2) =+        case jmEq1 typ1 typ2 of+        Just proof@Refl+            | eq1 d1 d2 -> Just proof+        _               -> Nothing++instance Eq1 ast => Eq1 (Datum ast) where+    eq1 (Datum _ _ d1) (Datum _ _ d2) = eq1 d1 d2++instance Eq1 ast => Eq (Datum ast a) where+    (==) = eq1++-- TODO: instance Read (Datum ast a)++instance Show1 ast => Show1 (Datum ast) where+    showsPrec1 p (Datum hint typ d) =+        showParen_011 p "Datum" hint typ d++instance Show1 ast => Show (Datum ast a) where+    showsPrec = showsPrec1+    show      = show1++instance Functor11 Datum where+    fmap11 f (Datum hint typ d) = Datum hint typ (fmap11 f d)++instance Foldable11 Datum where+    foldMap11 f (Datum _ _ d) = foldMap11 f d++instance Traversable11 Datum where+    traverse11 f (Datum hint typ d) = Datum hint typ <$> traverse11 f d+++----------------------------------------------------------------+infixr 7 `Et`, `PEt`++-- | The intermediate components of a data constructor. The intuition+-- behind the two indices is that the @[[HakaruFun]]@ is a functor+-- applied to the Hakaru type. Initially the @[[HakaruFun]]@ functor+-- will be the 'Code' associated with the Hakaru type; hence it's+-- the one-step unrolling of the fixed point for our recursive+-- datatypes. But as we go along, we'll be doing induction on the+-- @[[HakaruFun]]@ functor.+data DatumCode :: [[HakaruFun]] -> (Hakaru -> *) -> Hakaru -> * where+    -- BUG: haddock doesn't like annotations on GADT constructors+    -- <https://github.com/hakaru-dev/hakaru/issues/6>++    -- Skip rightwards along the sum.+    Inr :: !(DatumCode  xss abt a) -> DatumCode (xs ': xss) abt a+    -- Inject into the sum.+    Inl :: !(DatumStruct xs abt a) -> DatumCode (xs ': xss) abt a+++-- N.B., these \"Foo1\" instances rely on polymorphic recursion,+-- since the @code@ changes at each constructor. However, we don't+-- actually need to abstract over @code@ in order to define these+-- functions, because (1) we never existentially close over any+-- codes, and (2) the code is always getting smaller; so we have+-- a good enough inductive hypothesis from polymorphism alone.++#if __PARTIAL_DATUM_JMEQ__+-- This instance works, but recurses into non-working instances.+instance JmEq1 ast => JmEq1 (DatumCode xss ast) where+    jmEq1 (Inr c) (Inr d) = jmEq1 c d+    jmEq1 (Inl c) (Inl d) = jmEq1 c d+    jmEq1 _       _       = Nothing+#endif++instance Eq1 ast => Eq1 (DatumCode xss ast) where+    eq1 (Inr c) (Inr d) = eq1 c d+    eq1 (Inl c) (Inl d) = eq1 c d+    eq1 _       _       = False++instance Eq1 ast => Eq (DatumCode xss ast a) where+    (==) = eq1++-- TODO: instance Read (DatumCode xss abt a)++instance Show1 ast => Show1 (DatumCode xss ast) where+    showsPrec1 p (Inr d) = showParen_1 p "Inr" d+    showsPrec1 p (Inl d) = showParen_1 p "Inl" d++instance Show1 ast => Show (DatumCode xss ast a) where+    showsPrec = showsPrec1+    show      = show1++instance Functor11 (DatumCode xss) where+    fmap11 f (Inr d) = Inr (fmap11 f d)+    fmap11 f (Inl d) = Inl (fmap11 f d)++instance Foldable11 (DatumCode xss) where+    foldMap11 f (Inr d) = foldMap11 f d+    foldMap11 f (Inl d) = foldMap11 f d++instance Traversable11 (DatumCode xss) where+    traverse11 f (Inr d) = Inr <$> traverse11 f d+    traverse11 f (Inl d) = Inl <$> traverse11 f d+++----------------------------------------------------------------+data DatumStruct :: [HakaruFun] -> (Hakaru -> *) -> Hakaru -> * where+    -- BUG: haddock doesn't like annotations on GADT constructors+    -- <https://github.com/hakaru-dev/hakaru/issues/6>++    -- Combine components of the product. (\"et\" means \"and\" in Latin)+    Et  :: !(DatumFun    x         abt a)+        -> !(DatumStruct xs        abt a)+        ->   DatumStruct (x ': xs) abt a++    -- Close off the product.+    Done :: DatumStruct '[] abt a+++#if __PARTIAL_DATUM_JMEQ__+instance JmEq1 ast => JmEq1 (DatumStruct xs ast) where+    jmEq1 (Et c1 Done) (Et d1 Done) = jmEq1 c1 d1 -- HACK: to handle 'Done' in the cases where we can.+    jmEq1 (Et c1 c2)   (Et d1 d2)   = do+        Refl <- jmEq1 c1 d1+        Refl <- jmEq1 c2 d2+        Just Refl+    jmEq1 Done Done = Just (cannotProve "jmEq1@DatumStruct{Done}")+    jmEq1 _    _    = Nothing+#endif++instance Eq1 ast => Eq1 (DatumStruct xs ast) where+    eq1 (Et c1 c2) (Et d1 d2) = eq1 c1 d1 && eq1 c2 d2+    eq1 Done       Done       = True+    eq1 _          _          = False++instance Eq1 ast => Eq (DatumStruct xs ast a) where+    (==) = eq1++-- TODO: instance Read (DatumStruct xs abt a)++instance Show1 ast => Show1 (DatumStruct xs ast) where+    showsPrec1 p (Et d1 d2) = showParen_11 p "Et" d1 d2+    showsPrec1 _ Done       = showString     "Done"++instance Show1 ast => Show (DatumStruct xs ast a) where+    showsPrec = showsPrec1+    show      = show1++instance Functor11 (DatumStruct xs) where+    fmap11 f (Et d1 d2) = Et (fmap11 f d1) (fmap11 f d2)+    fmap11 _ Done       = Done++instance Foldable11 (DatumStruct xs) where+    foldMap11 f (Et d1 d2) = foldMap11 f d1 `mappend` foldMap11 f d2+    foldMap11 _ Done       = mempty++instance Traversable11 (DatumStruct xs) where+    traverse11 f (Et d1 d2) = Et <$> traverse11 f d1 <*> traverse11 f d2+    traverse11 _ Done       = pure Done+++----------------------------------------------------------------+-- TODO: do we like those constructor names? Should we change them?+data DatumFun :: HakaruFun -> (Hakaru -> *) -> Hakaru -> * where+    -- BUG: haddock doesn't like annotations on GADT constructors+    -- <https://github.com/hakaru-dev/hakaru/issues/6>++    -- Hit a leaf which isn't a recursive component of the datatype.+    Konst :: !(ast b) -> DatumFun ('K b) ast a+    -- Hit a leaf which is a recursive component of the datatype.+    Ident :: !(ast a) -> DatumFun 'I     ast a+++#if __PARTIAL_DATUM_JMEQ__+instance JmEq1 ast => JmEq1 (DatumFun x ast) where+    jmEq1 (Konst e) (Konst f) = do+        Refl <- jmEq1 e f -- This 'Refl' should be free because @x@ is fixed+        Just (cannotProve "jmEq1@DatumFun{Konst}")+    jmEq1 (Ident e) (Ident f) = jmEq1 e f+    jmEq1 _         _         = Nothing+#endif++instance Eq1 ast => Eq1 (DatumFun x ast) where+    eq1 (Konst e) (Konst f) = eq1 e f+    eq1 (Ident e) (Ident f) = eq1 e f+    eq1 _         _         = False++instance Eq1 ast => Eq (DatumFun x ast a) where+    (==) = eq1++-- TODO: instance Read (DatumFun x abt a)++instance Show1 ast => Show1 (DatumFun x ast) where+    showsPrec1 p (Konst e) = showParen_1 p "Konst" e+    showsPrec1 p (Ident e) = showParen_1 p "Ident" e++instance Show1 ast => Show (DatumFun x ast a) where+    showsPrec = showsPrec1+    show      = show1++instance Functor11 (DatumFun x) where+    fmap11 f (Konst e) = Konst (f e)+    fmap11 f (Ident e) = Ident (f e)++instance Foldable11 (DatumFun x) where+    foldMap11 f (Konst e) = f e+    foldMap11 f (Ident e) = f e++instance Traversable11 (DatumFun x) where+    traverse11 f (Konst e) = Konst <$> f e+    traverse11 f (Ident e) = Ident <$> f e+++----------------------------------------------------------------+-- In GHC 7.8 we can make the monomorphic smart constructors into+-- pattern synonyms, but 7.8 can't handle anything polymorphic (but+-- GHC 7.10 can). For libraries (e.g., "Language.Hakaru.Syntax.Prelude")+-- we can use functions to construct our Case_ statements, so library+-- designers don't need pattern synonyms. Whereas, for the internal+-- aspects of the compiler, we need to handle all possible Datum+-- values, so the pattern synonyms wouldn't even be helpful.++dTrue, dFalse :: Datum ast HBool+dTrue  = Datum tdTrue  sBool . Inl $ Done+dFalse = Datum tdFalse sBool . Inr . Inl $ Done++dUnit  :: Datum ast HUnit+dUnit  = Datum tdUnit sUnit . Inl $ Done++dPair :: (SingI a, SingI b) => ast a -> ast b -> Datum ast (HPair a b)+dPair = dPair_ sing sing++dPair_ :: Sing a -> Sing b -> ast a -> ast b -> Datum ast (HPair a b)+dPair_ a b x y =+    Datum tdPair (sPair a b) . Inl $ Konst x `Et` Konst y `Et` Done++dLeft :: (SingI a, SingI b) => ast a -> Datum ast (HEither a b)+dLeft = dLeft_ sing sing++dLeft_ :: Sing a -> Sing b -> ast a -> Datum ast (HEither a b)+dLeft_ a b =+    Datum tdLeft (sEither a b) . Inl . (`Et` Done) . Konst++dRight :: (SingI a, SingI b) => ast b -> Datum ast (HEither a b)+dRight = dRight_ sing sing++dRight_ :: Sing a -> Sing b -> ast b -> Datum ast (HEither a b)+dRight_ a b =+    Datum tdRight (sEither a b) . Inr . Inl . (`Et` Done) . Konst++dNil :: (SingI a) => Datum ast (HList a)+dNil = dNil_ sing++dNil_ :: Sing a -> Datum ast (HList a)+dNil_ a = Datum tdNil (sList a) . Inl $ Done++dCons :: (SingI a) => ast a -> ast (HList a) -> Datum ast (HList a)+dCons = dCons_ sing++dCons_ :: Sing a -> ast a -> ast (HList a) -> Datum ast (HList a)+dCons_ a x xs =+    Datum tdCons (sList a) . Inr . Inl $ Konst x `Et` Ident xs `Et` Done++dNothing :: (SingI a) => Datum ast (HMaybe a)+dNothing = dNothing_ sing++dNothing_ :: Sing a -> Datum ast (HMaybe a)+dNothing_ a = Datum tdNothing (sMaybe a) $ Inl Done++dJust :: (SingI a) => ast a -> Datum ast (HMaybe a)+dJust = dJust_ sing++dJust_ :: Sing a -> ast a -> Datum ast (HMaybe a)+dJust_ a = Datum tdJust (sMaybe a)  . Inr . Inl . (`Et` Done) . Konst+++----------------------------------------------------------------+tdTrue, tdFalse, tdUnit, tdPair, tdLeft, tdRight, tdNil, tdCons, tdNothing, tdJust :: Text+tdTrue    = Text.pack "true"+tdFalse   = Text.pack "false"+tdUnit    = Text.pack "unit"+tdPair    = Text.pack "pair"+tdLeft    = Text.pack "left"+tdRight   = Text.pack "right"+tdNil     = Text.pack "nil"+tdCons    = Text.pack "cons"+tdNothing = Text.pack "nothing"+tdJust    = Text.pack "just"+++----------------------------------------------------------------+----------------------------------------------------------------+-- TODO: negative patterns? (to facilitate reordering of case branches)+-- TODO: disjunctive patterns, a~la ML?+-- TODO: equality patterns for Nat\/Int? (what about Prob\/Real??)+-- TODO: exhaustiveness, non-overlap, dead-branch checking+--+-- | We index patterns by the type they scrutinize. This requires+-- the parser to be smart enough to build these patterns up, but+-- then it guarantees that we can't have 'Case_' of patterns which+-- can't possibly match according to our type system. In addition,+-- we also index patterns by the type of what variables they bind,+-- so that we can ensure that 'Branch' will never \"go wrong\".+-- Alas, this latter indexing means we can't use 'DatumCode',+-- 'DatumStruct', and 'DatumFun' but rather must define our own @P@+-- variants for pattern matching.+data Pattern :: [Hakaru] -> Hakaru -> * where+    -- BUG: haddock doesn't like annotations on GADT constructors+    -- <https://github.com/hakaru-dev/hakaru/issues/6>++    -- The \"don't care\" wildcard pattern.+    PWild :: Pattern '[]    a++    -- A pattern variable.+    PVar  :: Pattern '[ a ] a++    -- A data type constructor pattern. As with the 'Datum'+    -- constructor, the first component is a hint.+    PDatum+        :: {-# UNPACK #-} !Text+        -> !(PDatumCode (Code t) vars (HData' t))+        -> Pattern vars (HData' t)+++#if __PARTIAL_DATUM_JMEQ__+instance JmEq2 Pattern where+    jmEq2 PWild PWild = Just (Refl, cannotProve "jmEq2@Pattern{PWild}")+    jmEq2 PVar  PVar  = Just (cannotProve "jmEq2@Pattern{PVar}", cannotProve "jmEq2@Pattern{PVar}")+    jmEq2 (PDatum _ d1) (PDatum _ d2) =+        jmEq2_fake d1 d2+        where+        jmEq2_fake+            :: PDatumCode xss  vars1 a1+            -> PDatumCode xss' vars2 a2+            -> Maybe (TypeEq vars1 vars2, TypeEq a1 a2)+        jmEq2_fake =+            error "jmEq2@Pattern{PDatum}: can't recurse because Code isn't injective" -- so @xss@ and @xss'@ aren't guaranteed to be the same+    jmEq2 _ _ = Nothing++instance JmEq1 (Pattern vars) where+    jmEq1 p1 p2 = jmEq2 p1 p2 >>= \(_,proof) -> Just proof+#endif++instance Eq2 Pattern where+    eq2 PWild         PWild         = True+    eq2 PVar          PVar          = True+    eq2 (PDatum _ d1) (PDatum _ d2) = eq2 d1 d2+    eq2 _           _               = False++instance Eq1 (Pattern vars) where+    eq1 = eq2++instance Eq (Pattern vars a) where+    (==) = eq1++-- TODO: instance Read (Pattern vars a)++instance Show2 Pattern where+    showsPrec2 _ PWild           = showString     "PWild"+    showsPrec2 _ PVar            = showString     "PVar"+    showsPrec2 p (PDatum hint d) = showParen_02 p "PDatum" hint d++instance Show1 (Pattern vars) where+    showsPrec1 = showsPrec2+    show1      = show2++instance Show (Pattern vars a) where+    showsPrec = showsPrec1+    show      = show1++-- TODO: as necessary Functor22, Foldable22, Traversable22+++----------------------------------------------------------------+data PDatumCode :: [[HakaruFun]] -> [Hakaru] -> Hakaru -> * where+    PInr :: !(PDatumCode  xss vars a) -> PDatumCode (xs ': xss) vars a+    PInl :: !(PDatumStruct xs vars a) -> PDatumCode (xs ': xss) vars a+++#if __PARTIAL_DATUM_JMEQ__+instance JmEq2 (PDatumCode xss) where+    jmEq2 (PInr c) (PInr d) = jmEq2 c d+    jmEq2 (PInl c) (PInl d) = jmEq2 c d+    jmEq2 _        _        = Nothing++-- This instance works, but recurses into non-working instances.+instance JmEq1 (PDatumCode xss vars) where+    jmEq1 (PInr c) (PInr d) = jmEq1 c d+    jmEq1 (PInl c) (PInl d) = jmEq1 c d+    jmEq1 _        _        = Nothing+#endif++instance Eq2 (PDatumCode xss) where+    eq2 (PInr c) (PInr d) = eq2 c d+    eq2 (PInl c) (PInl d) = eq2 c d+    eq2 _        _        = False++instance Eq1 (PDatumCode xss vars) where+    eq1 = eq2++instance Eq (PDatumCode xss vars a) where+    (==) = eq1++-- TODO: instance Read (PDatumCode xss vars a)++instance Show2 (PDatumCode xss) where+    showsPrec2 p (PInr d) = showParen_2 p "PInr" d+    showsPrec2 p (PInl d) = showParen_2 p "PInl" d++instance Show1 (PDatumCode xss vars) where+    showsPrec1 = showsPrec2+    show1      = show2++instance Show (PDatumCode xss vars a) where+    showsPrec = showsPrec1+    show      = show1++-- TODO: as necessary Functor22, Foldable22, Traversable22++----------------------------------------------------------------+data PDatumStruct :: [HakaruFun] -> [Hakaru] -> Hakaru -> * where+    PEt :: !(PDatumFun    x         vars1 a)+        -> !(PDatumStruct xs        vars2 a)+        ->   PDatumStruct (x ': xs) (vars1 ++ vars2) a++    PDone :: PDatumStruct '[] '[] a+++-- This block of recursive functions are analogous to 'JmEq2' except+-- we only return the equality proof for the penultimate index+-- rather than both the penultimate and ultimate index. (Because+-- we /can/ return proofs for the penultimate index, but not for+-- the ultimate.) This is necessary for defining the @Eq1 (PDatumStruct+-- xs vars)@ and @Eq1 (Branch a abt)@ instances, since we need to+-- make sure the existential @vars@ match up.++-- N.B., that we can use 'Refl' in the 'PVar' case relies on the+-- fact that the @a@ parameter is fixed to be the same in both+-- patterns.+jmEq_P :: Pattern vs a -> Pattern ws a -> Maybe (TypeEq vs ws)+jmEq_P PWild         PWild         = Just Refl+jmEq_P PVar          PVar          = Just Refl+jmEq_P (PDatum _ p1) (PDatum _ p2) = jmEq_PCode p1 p2+jmEq_P _             _             = Nothing++jmEq_PCode+    :: PDatumCode xss vs a+    -> PDatumCode xss ws a+    -> Maybe (TypeEq vs ws)+jmEq_PCode (PInr p1) (PInr p2) = jmEq_PCode   p1 p2+jmEq_PCode (PInl p1) (PInl p2) = jmEq_PStruct p1 p2+jmEq_PCode _         _         = Nothing++jmEq_PStruct+    :: PDatumStruct xs vs a+    -> PDatumStruct xs ws a+    -> Maybe (TypeEq vs ws)+jmEq_PStruct (PEt c1 c2) (PEt d1 d2) = do+    Refl <- jmEq_PFun    c1 d1+    Refl <- jmEq_PStruct c2 d2+    Just Refl+jmEq_PStruct PDone PDone = Just Refl+jmEq_PStruct _     _     = Nothing++jmEq_PFun :: PDatumFun f vs a -> PDatumFun f ws a -> Maybe (TypeEq vs ws)+jmEq_PFun (PKonst p1) (PKonst p2) = jmEq_P p1 p2+jmEq_PFun (PIdent p1) (PIdent p2) = jmEq_P p1 p2+jmEq_PFun _           _           = Nothing+++#if __PARTIAL_DATUM_JMEQ__+instance JmEq2 (PDatumStruct xs) where+    jmEq2 (PEt c1 c2) (PEt d1 d2) = do+        (Refl, Refl) <- jmEq2 c1 d1+        (Refl, Refl) <- jmEq2 c2 d2+        Just (Refl, Refl)+    jmEq2 PDone PDone = Just (Refl, cannotProve "jmEq2@PDatumStruct{PDone}")+    jmEq2 _     _     = Nothing++instance JmEq1 (PDatumStruct xs vars) where+    jmEq1 p1 p2 = jmEq2 p1 p2 >>= \(_,proof) -> Just proof+#endif++instance Eq2 (PDatumStruct xs) where+    eq2 p1 p2 = maybe False (const True) $ jmEq_PStruct p1 p2++instance Eq1 (PDatumStruct xs vars) where+    eq1 = eq2++instance Eq (PDatumStruct xs vars a) where+    (==) = eq1++-- TODO: instance Read (PDatumStruct xs vars a)++instance Show2 (PDatumStruct xs) where+    showsPrec2 p (PEt d1 d2) = showParen_22 p "PEt" d1 d2+    showsPrec2 _ PDone       = showString     "PDone"++instance Show1 (PDatumStruct xs vars) where+    showsPrec1 = showsPrec2+    show1      = show2++instance Show (PDatumStruct xs vars a) where+    showsPrec = showsPrec1+    show      = show1++-- TODO: as necessary Functor22, Foldable22, Traversable22+++----------------------------------------------------------------+data PDatumFun :: HakaruFun -> [Hakaru] -> Hakaru -> * where+    PKonst :: !(Pattern vars b) -> PDatumFun ('K b) vars a+    PIdent :: !(Pattern vars a) -> PDatumFun 'I     vars a+++#if __PARTIAL_DATUM_JMEQ__+instance JmEq2 (PDatumFun x) where+    jmEq2 (PKonst p1) (PKonst p2) = do+        (Refl, Refl) <- jmEq2 p1 p2+        Just (Refl, cannotProve "jmEq2@PDatumFun{PKonst}")+    jmEq2 (PIdent p1) (PIdent p2) = jmEq2 p1 p2+    jmEq2 _ _ = Nothing++instance JmEq1 (PDatumFun x vars) where+    jmEq1 (PKonst e) (PKonst f) = do+        Refl <- jmEq1 e f+        Just (cannotProve "jmEq1@PDatumFun{PKonst}")+    jmEq1 (PIdent e) (PIdent f) = jmEq1 e f+    jmEq1 _          _          = Nothing+#endif++instance Eq2 (PDatumFun x) where+    eq2 (PKonst e) (PKonst f) = eq2 e f+    eq2 (PIdent e) (PIdent f) = eq2 e f+    eq2 _          _          = False++instance Eq1 (PDatumFun x vars) where+    eq1 = eq2++instance Eq (PDatumFun x vars a) where+    (==) = eq1++-- TODO: instance Read (PDatumFun x vars a)++instance Show2 (PDatumFun x) where+    showsPrec2 p (PKonst e) = showParen_2 p "PKonst" e+    showsPrec2 p (PIdent e) = showParen_2 p "PIdent" e++instance Show1 (PDatumFun x vars) where+    showsPrec1 = showsPrec2+    show1      = show2++instance Show (PDatumFun x vars a) where+    showsPrec = showsPrec1+    show      = show1++-- TODO: as necessary Functor22, Foldable22, Traversable22+++----------------------------------------------------------------+pTrue, pFalse :: Pattern '[] HBool+pTrue  = PDatum tdTrue  . PInl $ PDone+pFalse = PDatum tdFalse . PInr . PInl $ PDone++pUnit  :: Pattern '[] HUnit+pUnit  = PDatum tdUnit . PInl $ PDone++-- HACK: using undefined like that isn't going to help if we use+-- the variant of eqAppendIdentity that actually needs the Sing...+varsOfPattern :: Pattern vars a -> proxy vars+varsOfPattern _ = error "TODO: varsOfPattern"++pPair+    :: Pattern vars1 a+    -> Pattern vars2 b+    -> Pattern (vars1 ++ vars2) (HPair a b)+pPair x y =+    case eqAppendIdentity (varsOfPattern y) of+    Refl -> PDatum tdPair . PInl $ PKonst x `PEt` PKonst y `PEt` PDone++pLeft :: Pattern vars a -> Pattern vars (HEither a b)+pLeft x =+    case eqAppendIdentity (varsOfPattern x) of+    Refl -> PDatum tdLeft . PInl $ PKonst x `PEt` PDone++pRight :: Pattern vars b -> Pattern vars (HEither a b)+pRight y =+    case eqAppendIdentity (varsOfPattern y) of+    Refl -> PDatum tdRight . PInr . PInl $ PKonst y `PEt` PDone++pNil :: Pattern '[] (HList a)+pNil = PDatum tdNil . PInl $ PDone++pCons :: Pattern vars1 a+    -> Pattern vars2 (HList a)+    -> Pattern (vars1 ++ vars2) (HList a)+pCons x xs = +    case eqAppendIdentity (varsOfPattern xs) of+    Refl -> PDatum tdCons . PInr . PInl $ PKonst x `PEt` PIdent xs `PEt` PDone++pNothing :: Pattern '[] (HMaybe a)+pNothing = PDatum tdNothing . PInl $ PDone++pJust :: Pattern vars a -> Pattern vars (HMaybe a)+pJust x =+    case eqAppendIdentity (varsOfPattern x) of+    Refl -> PDatum tdJust . PInr . PInl $ PKonst x `PEt` PDone++----------------------------------------------------------------+-- TODO: a pretty infix syntax, like (:=>) or something?+--+-- TODO: this datatype is helpful for capturing the existential;+-- but other than that, it should be replaced\/augmented with a+-- type for pattern automata, so we can optimize case analysis.+--+-- TODO: if we used the argument order @Branch abt a b@ then we+-- could give @Foo2@ instances instead of just @Foo1@ instances.+-- Also would possibly let us talk about branches as profunctors+-- mapping @a@ to @b@. Would either of these actually be helpful+-- in practice for us?+data Branch+    (a   :: Hakaru)                  -- The type of the scrutinee.+    (abt :: [Hakaru] -> Hakaru -> *) -- The 'ABT' of the body.+    (b   :: Hakaru)                  -- The type of the body.+    = forall xs. Branch+        !(Pattern xs a)+        !(abt xs b)++instance Eq2 abt => Eq1 (Branch a abt) where+    eq1 (Branch p1 e1) (Branch p2 e2) =+        case jmEq_P p1 p2 of+        Nothing   -> False+        Just Refl -> eq2 e1 e2++instance Eq2 abt => Eq (Branch a abt b) where+    (==) = eq1++-- TODO: instance Read (Branch abt a b)++instance Show2 abt => Show1 (Branch a abt) where+    showsPrec1 p (Branch pat e) = showParen_22 p "Branch" pat e++instance Show2 abt => Show (Branch a abt b) where+    showsPrec = showsPrec1+    show      = show1++instance Functor21 (Branch a) where+    fmap21 f (Branch p e) = Branch p (f e)++instance Foldable21 (Branch a) where+    foldMap21 f (Branch _ e) = f e++instance Traversable21 (Branch a) where+    traverse21 f (Branch pat e) = Branch pat <$> f e++----------------------------------------------------------------+-- | A generalization of the 'Branch' type to allow a \"body\" of+-- any Haskell type.+data GBranch (a :: Hakaru) (r :: *)+    = forall xs. GBranch+        !(Pattern xs a)+        !(List1 Variable xs)+        r++instance Functor (GBranch a) where+    fmap f (GBranch pat vars x) = GBranch pat vars (f x)++instance F.Foldable (GBranch a) where+    foldMap f (GBranch _ _ x) = f x++instance T.Traversable (GBranch a) where+    traverse f (GBranch pat vars x) = GBranch pat vars <$> f x++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Syntax/DatumABT.hs view
@@ -0,0 +1,51 @@+{-# LANGUAGE CPP+           , DataKinds+           , PolyKinds+           , GADTs+           , TypeOperators+           , TypeFamilies+           , ExistentialQuantification+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.05.24+-- |+-- Module      :  Language.Hakaru.Syntax.DatumABT+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- Stuff that depends on both "Language.Hakaru.Syntax.ABT" and+-- "Language.Hakaru.Syntax.Datum"; factored out to avoid the cyclic+-- dependency issues.+----------------------------------------------------------------+module Language.Hakaru.Syntax.DatumABT+    ( fromGBranch+    , toGBranch+    ) where++import Language.Hakaru.Syntax.ABT+import Language.Hakaru.Syntax.Datum++----------------------------------------------------------------+----------------------------------------------------------------++fromGBranch+    :: (ABT syn abt)+    => GBranch a (abt '[] b)+    -> Branch a abt b+fromGBranch (GBranch pat vars e) =+    Branch pat (binds_ vars e)++toGBranch+    :: (ABT syn abt)+    => Branch a abt b+    -> GBranch a (abt '[] b)+toGBranch (Branch pat body) =+    uncurry (GBranch pat) (caseBinds body)++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Syntax/DatumCase.hs view
@@ -0,0 +1,378 @@+{-# LANGUAGE CPP+           , DataKinds+           , PolyKinds+           , GADTs+           , TypeOperators+           , TypeFamilies+           , Rank2Types+           , ScopedTypeVariables+           , FlexibleInstances+           , FlexibleContexts+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.04.28+-- |+-- Module      :  Language.Hakaru.Syntax.DatumCase+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- Reduction of case analysis on user-defined data types.+----------------------------------------------------------------+module Language.Hakaru.Syntax.DatumCase+    (+    -- * External API+      MatchResult(..)+    , DatumEvaluator+    , matchBranches+    , matchBranch++    -- * Internal API+    , MatchState(..)+    , matchTopPattern+    , matchPattern+    , viewDatum+    ) where++import Data.Proxy (Proxy(..))++import Language.Hakaru.Syntax.IClasses+-- TODO: make things polykinded so we can make our ABT implementation+-- independend of Hakaru's type system.+import Language.Hakaru.Types.DataKind+import Language.Hakaru.Syntax.Datum+import Language.Hakaru.Syntax.AST (Term(Datum_))+import Language.Hakaru.Syntax.ABT++import qualified Data.Text        as Text+import           Data.Number.Nat  (fromNat)+import           Text.PrettyPrint (Doc, (<+>), (<>))+import qualified Text.PrettyPrint as PP++----------------------------------------------------------------+----------------------------------------------------------------+-- TODO: would it be better to combine the 'Maybe' for failure into+-- the MatchResult itself instead of nesting the types? That'd make+-- the return types for 'matchBranch'\/'matchBranches' a bit trickier;+-- we'd prolly have to turn MatchResult into a monad (namely the+-- @Maybe (Either e (Writer (DList...) (Reader (List1...) a)))@+-- monad, or similar but restricting the Reader to a stream consumer).++-- BUG: haddock doesn't like annotations on GADT constructors. So+-- here we'll avoid using the GADT syntax, even though it'd make+-- the data type declaration prettier\/cleaner.+-- <https://github.com/hakaru-dev/hakaru/issues/6>+data MatchResult+    (ast :: Hakaru -> *)+    (abt :: [Hakaru] -> Hakaru -> *)+    (a   :: Hakaru)++    -- | Our 'DatumEvaluator' failed (perhaps in a nested pattern),+    -- thus preventing us from continuing case-reduction.+    = GotStuck++    -- | We successfully matched everything. The first argument+    -- gives the substitution for all the pattern variables. The+    -- second argument gives the body of the branch matched. N.B.,+    -- the substitution maps variables to some type @ast@ which is+    -- defined by the 'DatumEvaluator' used; it is not necessarily+    -- @abt '[]@! However, the body is definitely @abt '[]@ since+    -- thats what a 'Branch' stores after we account for the+    -- pattern-bound variables.+    --+    -- N.B., because the substitution may not have the right type+    -- (and because we are lazy), we do not perform substitution.+    -- Thus, the body has \"free\" variables which are defined\/bound+    -- in the association list. It's up to callers to perform the+    -- substitution, push the assocs onto the heap, or whatever.+    | Matched !(Assocs ast) !(abt '[] a)+++instance (Show1 ast, Show2 abt) => Show1 (MatchResult ast abt) where+    showsPrec1 _ GotStuck           = showString "GotStuck"+    showsPrec1 p (Matched rho body) =+        showParen (p > 9)+            ( showString "Matched "+            . showsPrec  11 rho+            . showString " "+            . showsPrec2 11 body+            )++instance (Show1 ast, Show2 abt) => Show (MatchResult ast abt a) where+    showsPrec = showsPrec1+    show      = show1+++-- | A function for trying to extract a 'Datum' from an arbitrary+-- term. This function is called every time we enter the 'matchPattern'+-- function. If this function returns 'Nothing' then the final+-- 'MatchResult' will be 'GotStuck'; otherwise, this function returns+-- 'Just' some 'Datum' that we can take apart to continue matching.+--+-- We don't care anything about the monad @m@, we just order the+-- effects in a top-down left-to-right manner as we traverse the+-- pattern. However, do note that we may end up calling this evaluator+-- repeatedly on the same argument, so it should be sufficiently+-- idempotent to work under those conditions. In particular,+-- 'matchBranches' will call it once on the top-level scrutinee for+-- each branch. (We should fix that, but it'll require using pattern+-- automata rather than a list of patterns\/branches.)+--+-- TODO: we could change this from returning 'Maybe' to returning+-- 'Either', that way the evaluator could give some reason for its+-- failure (we would store it in the 'GotStuck' constructor).+type DatumEvaluator ast m =+    forall t+    .  ast (HData' t)+    -> m (Maybe (Datum ast (HData' t)))+++-- TODO: see the todo for 'matchBranch' about changing the return+-- type. For this function we'd want to return the list of branches+-- including not just the stuck one but all the ones after it too.+-- (Though there's no need to return earlier branches, since we+-- already know they won't match.)+--+-- | Walk through a list of branches and try matching against them+-- in order. We just call 'matchBranches' repeatedly, and return+-- the first non-failure.+matchBranches+    :: (ABT Term abt, Monad m)+    => DatumEvaluator ast m+    -> ast a+    -> [Branch a abt b]+    -> m (Maybe (MatchResult ast abt b))+matchBranches getDatum e = go+    where+    -- TODO: isn't there a combinator in "Control.Monad" for this?+    -- TODO: lift the call to 'getDatum' out here, to avoid duplicating work+    go []     = return Nothing+    go (b:bs) = do+        match <- matchBranch getDatum e b+        case match of+            Nothing -> go bs+            Just _  -> return match+++-- TODO: change the result type to have values @Nothing@, @Just+-- (GotStuck modifiedScrutinee theStuckBranch)@ and @Just (Matched+-- assocs body)@. That is, give more information about getting+-- stuck, and avoid returning stupid stuff when we get stuck.+--+-- | Try matching against a single branch. This function is a thin+-- wrapper around 'matchTopPattern'; we just take apart the 'Branch'+-- to extract the pattern, list of variables to bind, and the body+-- of the branch.+matchBranch+    :: (ABT Term abt, Monad m)+    => DatumEvaluator ast m+    -> ast a+    -> Branch a abt b+    -> m (Maybe (MatchResult ast abt b))+matchBranch getDatum e (Branch pat body) = do+    let (vars,body') = caseBinds body+    match <- matchTopPattern getDatum e pat vars+    return $+        case match of+        Nothing                  -> Nothing+        Just GotStuck_           -> Just GotStuck+        Just (Matched_ rho Nil1) ->+            Just (Matched (toAssocs $ rho []) body')+++----------------------------------------------------------------+type DList a = [a] -> [a]++-- | The internal version of 'MatchResult' for giving us the properly+-- generalized inductive hypothesis.+data MatchState+    (ast  :: Hakaru -> *)+    (vars :: [Hakaru])++    -- | Our 'DatumEvaluator' failed (perhaps in a nested pattern),+    -- thus preventing us from continuing case-reduction.+    = GotStuck_++    -- TODO: we used to use @DList1 (Pair1 Variable (abt '[]))+    -- vars1@ for the first argument, with @vars1@ another parameter+    -- to the type; this would be helpful internally for guaranteeing+    -- that we return the right number and types of bindings.+    -- However, because the user-facing 'matchBranch' uses 'Branch'+    -- which existentializes over @vars1@, we'd need our user-facing+    -- 'MatchResult' type to also existentialize over @vars1@. Also,+    -- actually keeping track of @vars1@ makes the 'matchStruct'+    -- function much more difficult to get to typecheck. But,+    -- supposing we get that working, would the added guarantees+    -- of this more specific type be helpful for anyone else?+    --+    -- | We successfully matched everything (so far). The first+    -- argument gives the bindings for all the pattern variables+    -- we've already checked. The second argument gives the pattern+    -- variables remaining to be bound by checking the rest of the+    -- pattern.+    | Matched_+        (DList (Assoc ast))+        (List1 Variable vars)+++instance Show1 ast => Show (MatchState ast vars) where+    showsPrec p = shows . ppMatchState p++ppMatchState :: Show1 ast => Int -> MatchState ast vars -> Doc+ppMatchState _ GotStuck_ = PP.text "GotStuck_"+ppMatchState p (Matched_ boundVars unboundVars) =+    let f = "Matched_" in+    parens (p > 9)+        (PP.text f <+> PP.nest (1 + length f) (PP.sep+            [ ppList . map prettyPrecAssoc $ boundVars []+            , ppList $ ppVariables unboundVars+            ]))+    where+    ppList       = PP.brackets . PP.nest 1 . PP.fsep . PP.punctuate PP.comma+    parens True  = PP.parens   . PP.nest 1+    parens False = id++    prettyPrecAssoc :: Show1 ast => Assoc ast -> Doc+    prettyPrecAssoc (Assoc x e) =+        -- PP.cat $ ppFun 11 "Assoc" [ppVariable x, ...]+        let f = "Assoc" in+        PP.cat [PP.text f <+> PP.nest (1 + length f) (PP.sep+            [ ppVariable x+            , PP.text $ showsPrec1 11 e ""+            ])]++    ppVariables :: List1 Variable xs -> [Doc]+    ppVariables Nil1         = []+    ppVariables (Cons1 x xs) = ppVariable x : ppVariables xs++    ppVariable :: Variable a -> Doc+    ppVariable x = hint <> (PP.int . fromNat . varID) x+        where+        hint+            | Text.null (varHint x) = PP.char 'x' -- We used to use '_' but...+            | otherwise             = (PP.text . Text.unpack . varHint) x+++-- | Try matching against a (top-level) pattern. This function is+-- a thin wrapper around 'matchPattern' in order to restrict the+-- type.+matchTopPattern+    :: (Monad m)+    => DatumEvaluator ast m+    -> ast a+    -> Pattern vars a+    -> List1 Variable vars+    -> m (Maybe (MatchState ast '[]))+matchTopPattern getDatum e pat vars =+    case eqAppendIdentity (secondProxy pat) of+    Refl -> matchPattern getDatum e pat vars++secondProxy :: f i j -> Proxy i+secondProxy _ = Proxy+++-- | A trivial \"evaluation function\". If the term is already a+-- 'Datum_', then we extract the 'Datum' value; otherwise we fail.+-- You can 'return' the result to turn this into an 'DatumEvaluator'.+viewDatum+    :: (ABT Term abt)+    => abt '[] (HData' t)+    -> Maybe (Datum (abt '[]) (HData' t))+viewDatum e =+    caseVarSyn e (const Nothing) $ \t ->+        case t of+        Datum_ d -> Just d+        _        -> Nothing+++-- | Try matching against a (potentially nested) pattern. This+-- function generalizes 'matchTopPattern', which is necessary for+-- being able to handle nested patterns correctly. You probably+-- don't ever need to call this function.+matchPattern+    :: (Monad m)+    => DatumEvaluator ast m+    -> ast a+    -> Pattern vars1 a+    -> List1 Variable (vars1 ++ vars2)+    -> m (Maybe (MatchState ast vars2))+matchPattern getDatum e pat vars =+    case pat of+    PWild              -> return . Just $ Matched_ id vars+    PVar               ->+        case vars of+        Cons1 x vars'  -> return . Just $ Matched_ (Assoc x e :) vars'+        _              -> error "matchPattern: the impossible happened"+    PDatum _hint1 pat1 -> do+        mb <- getDatum e+        case mb of+            Nothing                     -> return $ Just GotStuck_+            Just (Datum _hint2 _typ2 d) -> matchCode getDatum d pat1 vars+++matchCode+    :: (Monad m)+    => DatumEvaluator ast m+    -> DatumCode  xss ast   (HData' t)+    -> PDatumCode xss vars1 (HData' t)+    -> List1 Variable (vars1 ++ vars2)+    -> m (Maybe (MatchState ast vars2))+matchCode getDatum d pat vars =+    case (d,pat) of+    (Inr d2, PInr pat2) -> matchCode   getDatum d2 pat2 vars+    (Inl d1, PInl pat1) -> matchStruct getDatum d1 pat1 vars+    _                   -> return Nothing+++matchStruct+    :: forall m ast xs t vars1 vars2+    .  (Monad m)+    => DatumEvaluator ast m+    -> DatumStruct  xs ast   (HData' t)+    -> PDatumStruct xs vars1 (HData' t)+    -> List1 Variable (vars1 ++ vars2)+    -> m (Maybe (MatchState ast vars2))+matchStruct getDatum d pat vars =+    case (d,pat) of+    (Done,     PDone)     -> return . Just $ Matched_ id vars+    (Et d1 d2, PEt p1 p2) ->+        let vars0 =+                case+                    eqAppendAssoc+                        (secondProxy p1)+                        (secondProxy p2)+                        (Proxy :: Proxy vars2) -- HACK: is there any other way to get our hands on @vars2@?+                of Refl -> vars+        in+        matchFun    getDatum d1 p1 vars0 `bindMMR` \xs1 vars1 ->+        matchStruct getDatum d2 p2 vars1 `bindMMR` \xs2 vars2 ->+        return . Just $ Matched_ (xs1 . xs2) vars2+    _ -> return Nothing+    where+    -- TODO: just turn @Maybe MatchState@ into a monad already?+    bindMMR m k = do+        mb <- m+        case mb of+            Nothing                  -> return Nothing+            Just GotStuck_           -> return $ Just GotStuck_+            Just (Matched_ xs vars') -> k xs vars'++matchFun+    :: (Monad m)+    => DatumEvaluator ast m+    -> DatumFun  x ast   (HData' t)+    -> PDatumFun x vars1 (HData' t)+    -> List1 Variable (vars1 ++ vars2)+    -> m (Maybe (MatchState ast vars2))+matchFun getDatum d pat vars =+    case (d,pat) of+    (Konst d2, PKonst p2) -> matchPattern getDatum d2 p2 vars+    (Ident d1, PIdent p1) -> matchPattern getDatum d1 p1 vars+    _                     -> return Nothing++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Syntax/IClasses.hs view
@@ -0,0 +1,821 @@+-- TODO: move this file somewhere else, like "Language.Hakaru.IClasses"+{-# LANGUAGE CPP+           , PolyKinds+           , DataKinds+           , TypeOperators+           , GADTs+           , TypeFamilies+           , Rank2Types+           , ScopedTypeVariables+           #-}+{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.04.28+-- |+-- Module      :  Language.Hakaru.Syntax.IClasses+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- A collection of classes generalizing standard classes in order+-- to support indexed types.+--+-- TODO: DeriveDataTypeable for all our newtypes?+----------------------------------------------------------------+module Language.Hakaru.Syntax.IClasses+    ( +    -- * Showing indexed types+      Show1(..), shows1, showList1+    , Show2(..), shows2, showList2+    -- ** Some more-generic helper functions for showing things+    , showListWith+    , showTuple+    -- ** some helpers for implementing the instances+    , showParen_0+    , showParen_1+    , showParen_2+    , showParen_01+    , showParen_02+    , showParen_11+    , showParen_12+    , showParen_22+    , showParen_010+    , showParen_011+    , showParen_111++    -- * Equality+    , Eq1(..)+    , Eq2(..)+    , TypeEq(..), symmetry, transitivity, congruence+    , JmEq1(..)+    , JmEq2(..)++    -- * Generalized abstract nonsense+    , Functor11(..), Fix11(..), cata11, ana11, hylo11+    , Functor12(..)+    , Functor21(..)+    , Functor22(..)+    , Foldable11(..), Lift1(..)+    , Foldable21(..), Lift2(..)+    , Foldable22(..)+    , Traversable11(..)+    , Traversable21(..)+    , Traversable22(..)+    +    -- * Helper types+    , Some1(..)+    , Some2(..)+    , Pair1(..), fst1, snd1+    , Pair2(..), fst2, snd2+    -- ** List types+    , type (++), eqAppendIdentity, eqAppendAssoc+    , List1(..), append1+    , DList1(..), toList1, fromList1, dnil1, dcons1, dsnoc1, dsingleton1, dappend1+    ) where++import Prelude hiding   (id, (.))+import Control.Category (Category(..))+import Unsafe.Coerce    (unsafeCoerce)+#if __GLASGOW_HASKELL__ < 710+import Data.Monoid      (Monoid(..))+import Control.Applicative+#endif++----------------------------------------------------------------+----------------------------------------------------------------+-- TODO: cf., <http://hackage.haskell.org/package/abt-0.1.1.0>+-- | Uniform variant of 'Show' for @k@-indexed types. This differs+-- from @transformers:@'Data.Functor.Classes.Show1' in being+-- polykinded, like it ought to be.+--+-- Alas, I don't think there's any way to derive instances the way+-- we can derive for 'Show'.+class Show1 (a :: k -> *) where+    {-# MINIMAL showsPrec1 | show1 #-}++    showsPrec1 :: Int -> a i -> ShowS+    showsPrec1 _ x s = show1 x ++ s++    show1 :: a i -> String+    show1 x = shows1 x ""++shows1 :: (Show1 a) => a i -> ShowS+shows1 =  showsPrec1 0++showList1 :: (Show1 a) => [a i] -> ShowS+showList1 = showListWith shows1++{-+-- BUG: these require (Show (i::k)) in the class definition of Show1+instance Show1 Maybe where+    showsPrec1 = showsPrec+    show1      = show++instance Show1 [] where+    showsPrec1 = showsPrec+    show1      = show++instance Show1 ((,) a) where+    showsPrec1 = showsPrec+    show1      = show++instance Show1 (Either a) where+    showsPrec1 = showsPrec+    show1      = show+-}+++----------------------------------------------------------------+-- TODO: how to show, in general, that @Show2 a@ implies @Show1 (a i)@ for all @i@... This is needed for 'Datum' which uses the 'LC_' trick...+class Show2 (a :: k1 -> k2 -> *) where+    {-# MINIMAL showsPrec2 | show2 #-}++    showsPrec2 :: Int -> a i j -> ShowS+    showsPrec2 _ x s = show2 x ++ s++    show2 :: a i j -> String+    show2 x = shows2 x ""++shows2 :: (Show2 a) => a i j -> ShowS+shows2 =  showsPrec2 0++showList2 :: Show2 a => [a i j] -> ShowS+showList2 = showListWith shows2+++----------------------------------------------------------------+-- This implementation taken from 'showList' in base-4.8:"GHC.Show",+-- generalizing over the showing function. Looks like this is available from base-4.8.2.0:"Text.Show"+showListWith :: (a -> ShowS) -> [a] -> ShowS+showListWith f = start+    where+    start []     s = "[]" ++ s+    start (x:xs) s = '[' : f x (go xs)+        where+        go []     = ']' : s+        go (y:ys) = ',' : f y (go ys)+++-- This implementation taken from 'show_tuple' in base-4.8:"GHC.Show",+-- verbatim.+showTuple :: [ShowS] -> ShowS+showTuple ss+    = showChar '('+    . foldr1 (\s r -> s . showChar ',' . r) ss+    . showChar ')'+++showParen_0 :: Show a => Int -> String -> a -> ShowS+showParen_0 p s e =+    showParen (p > 9)+        ( showString s+        . showString " "+        . showsPrec 11 e+        )++showParen_1 :: Show1 a => Int -> String -> a i -> ShowS+showParen_1 p s e =+    showParen (p > 9)+        ( showString s+        . showString " "+        . showsPrec1 11 e+        )++showParen_2 :: Show2 a => Int -> String -> a i j -> ShowS+showParen_2 p s e =+    showParen (p > 9)+        ( showString s+        . showString " "+        . showsPrec2 11 e+        )++showParen_01 :: (Show b, Show1 a) => Int -> String -> b -> a i -> ShowS+showParen_01 p s e1 e2 =+    showParen (p > 9)+        ( showString s+        . showString " "+        . showsPrec  11 e1+        . showString " "+        . showsPrec1 11 e2+        )+        +showParen_02 :: (Show b, Show2 a) => Int -> String -> b -> a i j -> ShowS+showParen_02 p s e1 e2 =+    showParen (p > 9)+        ( showString s+        . showString " "+        . showsPrec  11 e1+        . showString " "+        . showsPrec2 11 e2+        )++showParen_11 :: (Show1 a, Show1 b) => Int -> String -> a i -> b j -> ShowS+showParen_11 p s e1 e2 =+    showParen (p > 9)+        ( showString s+        . showString " "+        . showsPrec1 11 e1+        . showString " "+        . showsPrec1 11 e2+        )++showParen_12 :: (Show1 a, Show2 b) => Int -> String -> a i -> b j l -> ShowS+showParen_12 p s e1 e2 =+    showParen (p > 9)+        ( showString s+        . showString " "+        . showsPrec1 11 e1+        . showString " "+        . showsPrec2 11 e2+        )++showParen_22 :: (Show2 a, Show2 b) => Int -> String -> a i1 j1 -> b i2 j2 -> ShowS+showParen_22 p s e1 e2 =+    showParen (p > 9)+        ( showString s+        . showString " "+        . showsPrec2 11 e1+        . showString " "+        . showsPrec2 11 e2+        )++showParen_010+    :: (Show a, Show1 b, Show c)+    => Int -> String -> a -> b i -> c -> ShowS+showParen_010 p s e1 e2 e3 =+    showParen (p > 9)+        ( showString s+        . showString " "+        . showsPrec  11 e1+        . showString " "+        . showsPrec1 11 e2+        . showString " "+        . showsPrec  11 e3+        )++showParen_011+    :: (Show a, Show1 b, Show1 c)+    => Int -> String -> a -> b i -> c j -> ShowS+showParen_011 p s e1 e2 e3 =+    showParen (p > 9)+        ( showString s+        . showString " "+        . showsPrec  11 e1+        . showString " "+        . showsPrec1 11 e2+        . showString " "+        . showsPrec1 11 e3+        )++showParen_111+    :: (Show1 a, Show1 b, Show1 c)+    => Int -> String -> a i -> b j -> c k -> ShowS+showParen_111 p s e1 e2 e3 =+    showParen (p > 9)+        ( showString s+        . showString " "+        . showsPrec1 11 e1+        . showString " "+        . showsPrec1 11 e2+        . showString " "+        . showsPrec1 11 e3+        )++----------------------------------------------------------------+----------------------------------------------------------------+-- | Uniform variant of 'Eq' for homogeneous @k@-indexed types.+-- N.B., we keep this separate from the 'JmEq1' class because for+-- some types we may be able to decide 'eq1' while not being able+-- to decide 'jmEq1' (e.g., if using phantom types rather than+-- GADTs). N.B., this function returns value\/term equality! That+-- is, the following four laws must hold relating the 'Eq1' class+-- to the 'Eq' class:+--+--     (1) if @eq1 x y == True@, then @x@ and @y@ have the same+--         type index and @(x == y) == True@+--     (2) if @eq1 x y == False@ where @x@ and @y@ have the same+--         type index, then @(x == y) == False@+--     (3) if @(x == y) == True@, then @eq1 x y == True@+--     (4) if @(x == y) == False@, then @eq1 x y == False@+--+-- Alas, I don't think there's any way to derive instances the way+-- we can derive for 'Eq'.+class Eq1 (a :: k -> *) where+    eq1 :: a i -> a i -> Bool+    -- TODO: how do we give the default instance for whenever we have a JmEq1 instance?+    -- TODO: is there a way to require the induced @Eq (a i)@ instance to be given?+++class Eq2 (a :: k1 -> k2 -> *) where+    eq2 :: a i j -> a i j -> Bool++++----------------------------------------------------------------+----------------------------------------------------------------+-- TODO: it'd be okay to use @(:~:)@ from "Data.Typeable" instead of defining our own. Except that one doesn't define the Category instance, symmetry, or congruence...++-- | Concrete proofs of type equality. In order to make use of a+-- proof @p :: TypeEq a b@, you must pattern-match on the 'Refl'+-- constructor in order to show GHC that the types @a@ and @b@ are+-- equal.+data TypeEq :: k -> k -> * where+    Refl :: TypeEq a a++instance Category TypeEq where+    id          = Refl+    Refl . Refl = Refl++-- | Type equality is symmetric.+symmetry :: TypeEq a b -> TypeEq b a+symmetry Refl = Refl++-- | Type equality is transitive. N.B., this is has a more general+-- type than @(.)@+transitivity :: TypeEq a b -> TypeEq b c -> TypeEq a c+transitivity Refl Refl = Refl++-- | Type constructors are extensional.+congruence :: TypeEq a b -> TypeEq (f a) (f b)+congruence Refl = Refl+++-- TODO: Should we add an additional method which only checks for index equality, ignoring possible differences at the term\/value level?+--+-- | Uniform variant of 'Eq' for heterogeneous @k@-indexed types.+-- N.B., this function returns value\/term equality! That is, the+-- following four laws must hold relating the 'JmEq1' class to the+-- 'Eq1' class:+--+--     (1) if @jmEq1 x y == Just Refl@, then @x@ and @y@ have the+--         same type index and @eq1 x y == True@+--     (2) if @jmEq1 x y == Nothing@ where @x@ and @y@ have the+--         same type index, then @eq1 x y == False@+--     (3) if @eq1 x y == True@, then @jmEq1 x y == Just Refl@+--     (4) if @eq1 x y == False@, then @jmEq1 x y == Nothing@+--+-- Alas, I don't think there's any way to derive instances the way+-- we can derive for 'Eq'.+class Eq1 a => JmEq1 (a :: k -> *) where+    jmEq1 :: a i -> a j -> Maybe (TypeEq i j)++class Eq2 a => JmEq2 (a :: k1 -> k2 -> *) where+    jmEq2 :: a i1 j1 -> a i2 j2 -> Maybe (TypeEq i1 i2, TypeEq j1 j2)+++----------------------------------------------------------------+----------------------------------------------------------------+-- TODO: rather than having this plethora of classes for different indexing, define newtypes for 1-natural transformations, 2-natural transformations, etc; and then define a single higher-order functor class which is parameterized by the input and output categories.++-- | A functor on the category of @k@-indexed types (i.e., from+-- @k@-indexed types to @k@-indexed types). We unify the two indices,+-- because that seems the most helpful for what we're doing; we+-- could, of course, offer a different variant that maps @k1@-indexed+-- types to @k2@-indexed types...+--+-- Alas, I don't think there's any way to derive instances the way+-- we can derive for 'Functor'.+class Functor11 (f :: (k1 -> *) -> k2 -> *) where+    fmap11 :: (forall i. a i -> b i) -> f a j -> f b j+    +class Functor12 (f :: (k1 -> *) -> k2 -> k3 -> *) where+    fmap12 :: (forall i. a i -> b i) -> f a j l -> f b j l++-- | A functor from @(k1,k2)@-indexed types to @k3@-indexed types.+class Functor21 (f :: (k1 -> k2 -> *) -> k3 -> *) where+    fmap21 :: (forall h i. a h i -> b h i) -> f a j -> f b j+++-- | A functor from @(k1,k2)@-indexed types to @(k3,k4)@-indexed types.+class Functor22 (f :: (k1 -> k2 -> *) -> k3 -> k4 -> *) where+    fmap22 :: (forall h i. a h i -> b h i) -> f a j l -> f b j l+++----------------------------------------------------------------+newtype Fix11 (f :: (k -> *) -> k -> *) (i :: k) =+    Fix11 { unFix11 :: f (Fix11 f) i }++cata11+    :: forall f a j+    .  (Functor11 f)+    => (forall i. f a i -> a i)+    -> Fix11 f j -> a j+cata11 alg = go+    where+    go :: forall j'. Fix11 f j' -> a j'+    go = alg . fmap11 go . unFix11++ana11+    :: forall f a j+    .  (Functor11 f)+    => (forall i. a i -> f a i)+    -> a j -> Fix11 f j+ana11 coalg = go+    where+    go :: forall j'. a j' -> Fix11 f j'+    go = Fix11 . fmap11 go . coalg++hylo11+    :: forall f a b j+    .  (Functor11 f)+    => (forall i. a i -> f a i)+    -> (forall i. f b i -> b i)+    -> a j+    -> b j+hylo11 coalg alg = go+    where+    go :: forall j'. a j' -> b j'+    go = alg . fmap11 go . coalg++-- TODO: a tracing evaluator: <http://www.timphilipwilliams.com/posts/2013-01-16-fixing-gadts.html>+++----------------------------------------------------------------+-- TODO: in theory we could define some Monoid1 class to avoid the+-- explicit dependency on Lift1 in fold1's type. But we'd need that+-- Monoid1 class to have some sort of notion of combining things+-- at different indices...++-- | A foldable functor on the category of @k@-indexed types.+--+-- Alas, I don't think there's any way to derive instances the way+-- we can derive for 'Foldable'.+class Functor11 f => Foldable11 (f :: (k1 -> *) -> k2 -> *) where+    {-# MINIMAL fold11 | foldMap11 #-}++    fold11 :: (Monoid m) => f (Lift1 m) i -> m+    fold11 = foldMap11 unLift1++    foldMap11 :: (Monoid m) => (forall i. a i -> m) -> f a j -> m+    foldMap11 f = fold11 . fmap11 (Lift1 . f)++-- TODO: standard Foldable wrappers 'and11', 'or11', 'all11', 'any11',...+++class Functor21 f => Foldable21 (f :: (k1 -> k2 -> *) -> k3 -> *) where+    {-# MINIMAL fold21 | foldMap21 #-}++    fold21 :: (Monoid m) => f (Lift2 m) j -> m+    fold21 = foldMap21 unLift2++    foldMap21 :: (Monoid m) => (forall h i. a h i -> m) -> f a j -> m+    foldMap21 f = fold21 . fmap21 (Lift2 . f)+++class Functor22 f =>+    Foldable22 (f :: (k1 -> k2 -> *) -> k3 -> k4 -> *)+    where+    {-# MINIMAL fold22 | foldMap22 #-}++    fold22 :: (Monoid m) => f (Lift2 m) j l -> m+    fold22 = foldMap22 unLift2++    foldMap22 :: (Monoid m) => (forall h i. a h i -> m) -> f a j l -> m+    foldMap22 f = fold22 . fmap22 (Lift2 . f)+++----------------------------------------------------------------+----------------------------------------------------------------+class Foldable11 t => Traversable11 (t :: (k1 -> *) -> k2 -> *) where+    traverse11+        :: Applicative f+        => (forall i. a i -> f (b i))+        -> t a j+        -> f (t b j)+    {-+    sequenceA :: Applicative f => t (f a) -> f (t a)+    mapM :: Monad m => (a -> m b) -> t a -> m (t b)+    sequence :: Monad m => t (m a) -> m (t a)+    -}+++class Foldable21 t => Traversable21 (t :: (k1 -> k2 -> *) -> k3 -> *) where+    traverse21+        :: Applicative f+        => (forall h i. a h i -> f (b h i))+        -> t a j+        -> f (t b j)+    ++class Foldable22 t =>+    Traversable22 (t :: (k1 -> k2 -> *) -> k3 -> k4 -> *)+    where+    traverse22+        :: Applicative f+        => (forall h i. a h i -> f (b h i))+        -> t a j l+        -> f (t b j l)+++----------------------------------------------------------------+----------------------------------------------------------------+-- | Any unindexed type can be lifted to be (trivially) @k@-indexed.+newtype Lift1 (a :: *) (i :: k) =+    Lift1 { unLift1 :: a }+    deriving (Read, Show, Eq, Ord)++instance Show a => Show1 (Lift1 a) where+    showsPrec1 p (Lift1 x) = showsPrec p x+    show1        (Lift1 x) = show x++instance Eq a => Eq1 (Lift1 a) where+    eq1 (Lift1 a) (Lift1 b) = a == b+++----------------------------------------------------------------+-- | Any unindexed type can be lifted to be (trivially) @(k1,k2)@-indexed.+newtype Lift2 (a :: *) (i :: k1) (j :: k2) =+    Lift2 { unLift2 :: a }+    deriving (Read, Show, Eq, Ord)++instance Show a => Show2 (Lift2 a) where+    showsPrec2 p (Lift2 x) = showsPrec p x+    show2        (Lift2 x) = show x++instance Show a => Show1 (Lift2 a i) where+    showsPrec1 p (Lift2 x) = showsPrec p x+    show1        (Lift2 x) = show x+    +instance Eq a => Eq2 (Lift2 a) where+    eq2 (Lift2 a) (Lift2 b) = a == b+    +instance Eq a => Eq1 (Lift2 a i) where+    eq1 (Lift2 a) (Lift2 b) = a == b+++----------------------------------------------------------------+-- BUG: haddock doesn't like annotations on GADT constructors. So+-- here we'll avoid using the GADT syntax, even though it'd make+-- the data type declaration prettier\/cleaner.+-- <https://github.com/hakaru-dev/hakaru/issues/6>+--+-- | Existentially quantify over a single index.+-- TODO: replace 'SomeVariable' with @(Some1 Variable)@+data Some1 (a :: k -> *)+    = forall i. Some1 !(a i)++instance Show1 a => Show (Some1 a) where+    showsPrec p (Some1 x) = showParen_1 p "Some1" x++instance JmEq1 a  => Eq (Some1 a) where+    Some1 x == Some1 y = maybe False (const True) (jmEq1 x y)+++-- | Existentially quantify over two indices.+data Some2 (a :: k1 -> k2 -> *)+    = forall i j. Some2 !(a i j)++instance Show2 a => Show (Some2 a) where+    showsPrec p (Some2 x) = showParen_2 p "Some2" x++instance JmEq2 a  => Eq (Some2 a) where+    Some2 x == Some2 y = maybe False (const True) (jmEq2 x y)+++----------------------------------------------------------------+-- | A lazy pairing of identically @k@-indexed values.+data Pair1 (a :: k -> *) (b :: k -> *) (i :: k) =+    Pair1 (a i) (b i)++fst1 :: Pair1 a b i -> a i+fst1 (Pair1 x _) = x++snd1 :: Pair1 a b i -> b i+snd1 (Pair1 _ y) = y++instance (Show1 a, Show1 b) => Show1 (Pair1 a b) where+    showsPrec1 p (Pair1 x y) = showParen_11 p "Pair1" x y++instance (Show1 a, Show1 b) => Show (Pair1 a b i) where+    showsPrec = showsPrec1+    show      = show1++-- TODO: derived Eq, JmEq, functor, foldable, traversable instances++----------------------------------------------------------------+-- | A lazy pairing of identically @(k1,k2)@-indexed values.+data Pair2 (a :: k1 -> k2 -> *) (b :: k1 -> k2 -> *) (i :: k1) (j :: k2) =+    Pair2 (a i j) (b i j)++fst2 :: Pair2 a b i j -> a i j+fst2 (Pair2 x _) = x++snd2 :: Pair2 a b i j -> b i j+snd2 (Pair2 _ y) = y++instance (Show2 a, Show2 b) => Show2 (Pair2 a b) where+    showsPrec2 p (Pair2 x y) = showParen_22 p "Pair2" x y++instance (Show2 a, Show2 b) => Show1 (Pair2 a b i) where+    showsPrec1 = showsPrec2+    show1      = show2++instance (Show2 a, Show2 b) => Show (Pair2 a b i j) where+    showsPrec = showsPrec1+    show      = show1++-- TODO: derived Eq, JmEq, functor, foldable, traversable instances+++----------------------------------------------------------------+----------------------------------------------------------------+-- TODO: move all the list stuff off somewhere else++-- BUG: how do we actually use the term-level @(++)@ at the type level? Or do we have to redefine it ourselves (as below)? If we define it ourselves, how can we make sure it's usable? In particular, how can we prove associativity and that @'[]@ is a /two-sided/ identity element?+type family (xs :: [k]) ++ (ys :: [k]) :: [k] where+    '[]       ++ ys = ys+    (x ': xs) ++ ys = x ': (xs ++ ys) ++{-+-- BUG: having the instances for @[[HakaruFun]]@ and @[HakaruFun]@ precludes giving a general kind-polymorphic data instance for type-level lists; so we have to monomorphize it to just the @[Hakaru]@ kind.+-- TODO: we should figure out some way to clean that up without introducing too much ambiguity\/overloading of the constructor names.+data instance Sing (xs :: [Hakaru]) where+    SNil  :: Sing ('[] :: [Hakaru])+    SCons :: !(Sing x) -> !(Sing xs) -> Sing ((x ': xs) :: [Hakaru])++-- BUG: ghc calls all these orphan instances, even though the data instance is defined here... Will that actually cause problems? Should we move this to TypeEq.hs?+instance Show1 (Sing :: [Hakaru] -> *) where+    showsPrec1 p s =+        case s of+        SNil        -> showString     "SNil"+        SCons s1 s2 -> showParen_11 p "SCons" s1 s2+instance Show (Sing (xs :: [Hakaru])) where+    showsPrec = showsPrec1+    show      = show1+instance SingI ('[] :: [Hakaru]) where+    sing = SNil+instance (SingI x, SingI xs) => SingI ((x ': xs) :: [Hakaru]) where+    sing = SCons sing sing+-}+++-- | The empty list is (also) a right-identity for @('++')@. Because+-- we define @('++')@ by induction on the first argument, this+-- identity doesn't come for free but rather must be proven.+eqAppendIdentity :: proxy xs -> TypeEq xs (xs ++ '[])+-- This version should be used for runtime performance+eqAppendIdentity _ = unsafeCoerce Refl+{-+-- This version demonstrates that our use of unsafeCoerce is sound+-- BUG: to have an argument of type @Sing xs@, instead of an arbitrary @proxy xs@, we'd need to store the singleton somewhere (prolly in the 'Branch', for the use site in TypeCheck.hs) or else produce it somehow+eqAppendIdentity :: Sing (xs :: [Hakaru]) -> TypeEq xs (xs ++ '[])+eqAppendIdentity SNil        = Refl+eqAppendIdentity (SCons _ s) = case eqAppendIdentity s of Refl -> Refl+-}+++-- To make a version that doesn't require proxies, we'd need to+-- enable -XAllowAmbiguousTypes. We'd need to do this even just to+-- drop the second or third proxies, which aren't needed for the+-- safe version.+--+-- | @('++')@ is associative. This identity doesn't come for free+-- but rather must be proven.+eqAppendAssoc+    :: proxy1 xs+    -> proxy2 ys+    -> proxy3 zs+    -> TypeEq ((xs ++ ys) ++ zs) (xs ++ (ys ++ zs))+-- This version should be used for runtime performance+eqAppendAssoc _ _ _ = unsafeCoerce Refl+{-+-- This version demonstrates that our use of unsafeCoerce is sound+-- BUG: to have the arguments be of type @Sing xs@, instead of arbitrary proxy types, we'd need to store the singletons somewhere (for the use site in TypeCheck.hs), but where?+eqAppendAssoc+    :: Sing (xs :: [Hakaru])+    -> Sing (ys :: [Hakaru])+    -> Sing (zs :: [Hakaru])+    -> TypeEq ((xs ++ ys) ++ zs) (xs ++ (ys ++ zs))+eqAppendAssoc SNil         _  _  = Refl+eqAppendAssoc (SCons _ sx) sy sz =+    case eqAppendAssoc sx sy sz of Refl -> Refl+-}++-- TODO: eqAppendNil :: proxy xs -> proxy ys -> TypeEq '[] (xs ++ ys) -> (TypeEq '[] xs, TypeEq '[] ys)+++----------------------------------------------------------------+infixr 5 `Cons1`++-- | A /lazy/ list of @k@-indexed elements, itself indexed by the+-- list of indices+data List1 :: (k -> *) -> [k] -> * where+    Nil1  :: List1 a '[]+    Cons1 :: a x -> List1 a xs -> List1 a (x ': xs)+++append1 :: List1 a xs -> List1 a ys -> List1 a (xs ++ ys)+append1 Nil1         ys = ys+append1 (Cons1 x xs) ys = Cons1 x (append1 xs ys)+++instance Show1 a => Show1 (List1 a) where+    showsPrec1 _ Nil1         = showString     "Nil1"+    showsPrec1 p (Cons1 x xs) = showParen_11 p "Cons1" x xs++instance Show1 a => Show (List1 a xs) where+    showsPrec = showsPrec1+    show      = show1++instance JmEq1 a  => JmEq1 (List1 a) where+    jmEq1 Nil1         Nil1         = Just Refl+    jmEq1 (Cons1 x xs) (Cons1 y ys) =+        jmEq1 x  y  >>= \Refl ->+        jmEq1 xs ys >>= \Refl ->+        Just Refl+    jmEq1 _ _ = Nothing++instance Eq1 a  => Eq1 (List1 a) where+    eq1 Nil1         Nil1         = True+    eq1 (Cons1 x xs) (Cons1 y ys) = eq1 x y && eq1 xs ys+    eq1 _            _            = False++instance Eq1 a  => Eq (List1 a xs) where+    (==) = eq1++instance Functor11 List1 where+    fmap11 _ Nil1         = Nil1+    fmap11 f (Cons1 x xs) = Cons1 (f x) (fmap11 f xs)++instance Foldable11 List1 where+    foldMap11 _ Nil1         = mempty+    foldMap11 f (Cons1 x xs) = f x `mappend` foldMap11 f xs++instance Traversable11 List1 where+    traverse11 _ Nil1         = pure Nil1+    traverse11 f (Cons1 x xs) = Cons1 <$> f x <*> traverse11 f xs+++----------------------------------------------------------------+-- TODO: cf the interface of <https://hackage.haskell.org/package/dlist-0.7.1.2/docs/Data-DList.html>+-- | A difference-list variant of 'List1'.+newtype DList1 a xs =+    DList1 { unDList1 :: forall ys. List1 a ys -> List1 a (xs ++ ys) }+++toList1 :: DList1 a xs -> List1 a xs+toList1 dx@(DList1 xs) =+    case eqAppendIdentity dx of+    Refl -> xs Nil1++fromList1 :: List1 a xs -> DList1 a xs+fromList1 xs = DList1 (append1 xs)+    -- N.B., using @DList1 . append1@ doesn't type check++dnil1 :: DList1 a '[]+dnil1 = DList1 id++dcons1 :: a x -> DList1 a xs -> DList1 a (x ': xs)+dcons1 x (DList1 xs) = DList1 (Cons1 x . xs)++-- TODO: for this access pattern it's prolly better to define some @DListR@ where the index is in the reverse order of the list itself (or else uses type-level snoc-lists); that way we can avoid needing to use 'eqAppendAssoc' at every step...+dsnoc1 :: DList1 a xs -> a x -> DList1 a (xs ++ '[ x ])+dsnoc1 dx@(DList1 xs) x =+    DList1 $ \ys ->+        case eqAppendAssoc dx (dsingleton1 x) ys of+        Refl -> xs (Cons1 x ys)++-- HACK: we need to give this a top-level definition rather than+-- inlining it in order to prove that the resulting index is @[x]@+-- rather than possibly some other @(x:xs)@. No, I'm not sure why+-- GHC can't infer that...+dsingleton1 :: a x -> DList1 a '[ x ]+dsingleton1 x = DList1 (Cons1 x)++dappend1 :: DList1 a xs -> DList1 a ys -> DList1 a (xs ++ ys)+dappend1 dx@(DList1 xs) dy@(DList1 ys) =+    DList1 $ \zs ->+        case eqAppendAssoc dx dy zs of+        Refl -> xs (ys zs)++{-+instance Show1 a => Show1 (DList1 a) where+    showsPrec1 p xs =++instance Show1 a => Show (DList1 a xs) where+    showsPrec = showsPrec1+    show      = show1++instance JmEq1 a => JmEq1 (DList1 a) where+    jmEq1 xs ys =++instance Eq1 a => Eq1 (DList1 a) where+    eq1 xs ys =++instance Eq1 a => Eq (DList1 a xs) where+    (==) = eq1++instance Functor11 DList1 where+    fmap11 f xs =++instance Foldable11 DList1 where+    foldMap11 f xs =++instance Traversable11 DList1 where+    traverse11 f xs =+-}++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Syntax/Prelude.hs view
@@ -0,0 +1,1634 @@+{-# LANGUAGE TypeOperators+           , KindSignatures+           , DataKinds+           , TypeFamilies+           , GADTs+           , FlexibleInstances+           , NoImplicitPrelude+           , ScopedTypeVariables+           , FlexibleContexts+           , Rank2Types+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.04.22+-- |+-- Module      :  Language.Hakaru.Syntax.Prelude+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- A replacement for Haskell's Prelude, using the familiar symbols+-- in order to construct 'AST's and 'ABT's. This is only necessary+-- if we want to use Hakaru as an embedded language in Haskell, but+-- it also provides some examples of how to use the infrastructure.+--+-- TODO: is there a way to get rid of the need to specify @'[]@ everywhere in here? Some sort of distinction between the Var vs the Open parts of View?+----------------------------------------------------------------+module Language.Hakaru.Syntax.Prelude+    (+    -- * Basic syntax+    -- ** Types and coercions+      ann_, triv, memo+    , coerceTo_, fromProb, nat2int, nat2prob, fromInt, nat2real+    , unsafeFrom_, unsafeProb, unsafeProbFraction, unsafeProbFraction_, unsafeProbSemiring, unsafeProbSemiring_+    -- ** Numeric literals+    , literal_, nat_, int_, prob_, real_+    , fromRational, half, third+    -- ** Booleans+    , true, false, bool_, if_+    , not, (&&), and, (||), or, nand, nor+    -- ** Equality and ordering+    , (==), (/=), (<), (<=), (>), (>=), min, minimum, max, maximum+    -- ** Semirings+    , zero, zero_, one, one_, (+), sum, (*), prod, (^), square+    , unsafeMinusNat, unsafeMinusProb, unsafeMinus, unsafeMinus_+    , unsafeDiv, unsafeDiv_+    -- ** Rings+    , (-), negate, negative, abs, abs_, signum+    -- ** Fractional+    , (/), recip, (^^)+    -- ** Radical+    , sqrt, thRootOf+    -- ** Integration+    , integrate, summate, product+    -- ** Continuous+    , RealProb(..), Integrable(..)+    , betaFunc+    , log, logBase+    , negativeInfinity+    -- *** Trig+    , sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh+    +    -- * Measures+    -- ** Abstract nonsense+    , dirac, (<$>), (<*>), (<*), (*>), (>>=), (>>), bindx, liftM2+    -- ** Linear operators+    , superpose, (<|>)+    , weight, withWeight, weightedDirac+    , reject, guard, withGuard+    -- ** Measure operators+    -- | When two versions of the same operator are given, the one without the prime builds an AST using the built-in operator, whereas the one with the prime is a default definition in terms of more primitive measure operators.+    , lebesgue+    , counting+    , densityCategorical, categorical, categorical'+    , densityUniform, uniform, uniform'+    , densityNormal, normal, normal'+    , densityPoisson, poisson, poisson'+    , densityGamma, gamma, gamma'+    , densityBeta, beta, beta', beta''+    , plateWithVar, plate, plate'+    , chain, chain'+    , invgamma+    , exponential+    , chi2+    , cauchy+    , laplace+    , studentT+    , weibull+    , bern+    , mix+    , binomial+    , negativeBinomial+    , geometric+    , multinomial+    , dirichlet++    -- * Data types (other than booleans)+    , datum_+    -- * Case and Branch+    , case_, branch+    -- ** HUnit+    , unit+    -- ** HPair+    , pair, pair_, unpair, fst, snd, swap+    -- ** HEither+    , left, right, uneither+    -- ** HMaybe+    , nothing, just, maybe, unmaybe+    -- ** HList+    , nil, cons, list++    -- * Lambda calculus+    , lam, lamWithVar, let_+    , app, app2, app3++    -- * Arrays+    , empty, arrayWithVar, array, (!), size, reduce+    , sumV, summateV, appendV, mapV, mapWithIndex, normalizeV, constV, unitV, zipWithV++    -- * Implementation details+    , primOp0_, primOp1_, primOp2_, primOp3_+    , arrayOp0_, arrayOp1_, arrayOp2_, arrayOp3_+    , measure0_, measure1_, measure2_+    , unsafeNaryOp_, naryOp_withIdentity, naryOp2_+    ) where++-- TODO: implement and use Prelude's fromInteger and fromRational, so we can use numeric literals!+import Prelude (Maybe(..), Bool(..), Integer, Rational, ($), flip, const, error)+import qualified Prelude+import           Data.Sequence       (Seq)+import qualified Data.Sequence       as Seq+import qualified Data.Text           as Text+import           Data.List.NonEmpty  (NonEmpty(..))+import qualified Data.List.NonEmpty  as L+import           Data.Semigroup      (Semigroup(..))+import           Control.Category    (Category(..))++import Data.Number.Natural+import Language.Hakaru.Types.DataKind+import Language.Hakaru.Types.Sing (Sing(..), SingI(sing), sUnPair, sUnEither, sUnMaybe, sUnMeasure, sUnArray)+import Language.Hakaru.Syntax.TypeOf+import Language.Hakaru.Types.HClasses+import Language.Hakaru.Types.Coercion+import Language.Hakaru.Syntax.AST+import Language.Hakaru.Syntax.Datum+import Language.Hakaru.Syntax.ABT hiding (View(..))++----------------------------------------------------------------+----- Helper combinators for defining our EDSL+{-+Below we implement a lot of simple optimizations; however, these+optimizations only apply if the client uses the type class methods+to produce the AST. We should implement a stand-alone function which+performs these sorts of optimizations, as a program transformation.+-}+-- TODO: constant propogation++-- TODO: NBE to get rid of administrative redexes.+app :: (ABT Term abt) => abt '[] (a ':-> b) -> abt '[] a -> abt '[] b+app e1 e2 = syn (App_ :$ e1 :* e2 :* End)++app2 :: (ABT Term abt) => abt '[] (a ':-> b ':-> c) -> abt '[] a -> abt '[] b -> abt '[] c+app2 = (app .) . app++app3 :: (ABT Term abt) => abt '[] (a ':-> b ':-> c ':-> d) -> abt '[] a -> abt '[] b -> abt '[] c -> abt '[] d+app3 = (app2 .) . app++triv :: TrivialABT Term '[] a -> TrivialABT Term '[] a+triv = id++memo :: MemoizedABT Term '[] a -> MemoizedABT Term '[] a+memo = id++primOp0_ :: (ABT Term abt) => PrimOp '[] a -> abt '[] a+primOp0_ o = syn (PrimOp_ o :$ End)++primOp1_+    :: (ABT Term abt)+    => PrimOp '[ a ] b+    -> abt '[] a -> abt '[] b+primOp1_ o e1 = syn (PrimOp_ o :$ e1 :* End)++primOp2_+    :: (ABT Term abt)+    => PrimOp '[ a, b ] c+    -> abt '[] a -> abt '[] b -> abt '[] c+primOp2_ o e1 e2 = syn (PrimOp_ o :$ e1 :* e2 :* End)++primOp3_+    :: (ABT Term abt)+    => PrimOp '[ a, b, c ] d+    -> abt '[] a -> abt '[] b -> abt '[] c -> abt '[] d+primOp3_ o e1 e2 e3 = syn (PrimOp_ o :$ e1 :* e2 :* e3 :* End)++arrayOp0_ :: (ABT Term abt) => ArrayOp '[] a -> abt '[] a+arrayOp0_ o = syn (ArrayOp_ o :$ End)++arrayOp1_+    :: (ABT Term abt)+    => ArrayOp '[ a ] b+    -> abt '[] a -> abt '[] b+arrayOp1_ o e1 = syn (ArrayOp_ o :$ e1 :* End)++arrayOp2_+    :: (ABT Term abt)+    => ArrayOp '[ a, b ] c+    -> abt '[] a -> abt '[] b -> abt '[] c+arrayOp2_ o e1 e2 = syn (ArrayOp_ o :$ e1 :* e2 :* End)++arrayOp3_+    :: (ABT Term abt)+    => ArrayOp '[ a, b, c ] d+    -> abt '[] a -> abt '[] b -> abt '[] c -> abt '[] d+arrayOp3_ o e1 e2 e3 = syn (ArrayOp_ o :$ e1 :* e2 :* e3 :* End)++measure0_ :: (ABT Term abt) => MeasureOp '[] a -> abt '[] ('HMeasure a)+measure0_ o = syn (MeasureOp_ o :$ End)++measure1_+    :: (ABT Term abt)+    => MeasureOp '[ a ] b+    -> abt '[] a -> abt '[] ('HMeasure b)+measure1_ o e1 = syn (MeasureOp_ o :$ e1 :* End)++measure2_+    :: (ABT Term abt)+    => MeasureOp '[ a, b ] c+    -> abt '[] a -> abt '[] b -> abt '[] ('HMeasure c)+measure2_ o e1 e2 = syn (MeasureOp_ o :$ e1 :* e2 :* End)+++-- N.B., we don't take advantage of commutativity, for more predictable+-- AST outputs. However, that means we can end up being slow...+--+-- N.B., we also don't try to eliminate the identity elements or+-- do cancellations because (a) it's undecidable in general, and+-- (b) that's prolly better handled as a post-processing simplification+-- step+--+-- TODO: generalize these two from [] to Foldable?++-- | Apply an n-ary operator to a list. This smart constructor will+-- flatten nested calls to the same operator. And if there is exactly+-- one element in the flattened sequence, then it will remove the+-- 'NaryOp_' node from the AST.+--+-- N.B., if the flattened sequence is empty, this smart constructor+-- will return an AST which applies the operator to the empty+-- sequence; which may or may not be unsafe. If the operator has+-- an identity element, then it's fine (operating on the empty+-- sequence evaluates to the identity element). However, if the+-- operator doesn't have an identity, then the generated code will+-- error whenever we attempt to run it.+unsafeNaryOp_ :: (ABT Term abt) => NaryOp a -> [abt '[] a] -> abt '[] a+unsafeNaryOp_ o = naryOp_withIdentity o (syn $ NaryOp_ o Seq.empty)+++-- | A variant of 'unsafeNaryOp_' which will replace operating over+-- the empty sequence with a specified identity element. The produced+-- AST has the same semantics, we're just preemptively+-- evaluating\/simplifying the 'NaryOp_' node of the AST.+--+-- N.B., this function does not simplify away the identity element+-- if it exists in the flattened sequence! We should add that in+-- the future.+naryOp_withIdentity+    :: (ABT Term abt) => NaryOp a -> abt '[] a -> [abt '[] a] -> abt '[] a+naryOp_withIdentity o i = go Seq.empty+    where+    go es [] =+        case Seq.viewl es of+        Seq.EmptyL   -> i+        e Seq.:< es' ->+            case Seq.viewl es' of+            Seq.EmptyL -> e+            _          -> syn $ NaryOp_ o es+    go es (e:es') =+        case matchNaryOp o e of+        Nothing   -> go (es Seq.|> e)    es'+        Just es'' -> go (es Seq.>< es'') es'+++-- TODO: is this actually worth breaking out, performance-wise? Or should we simply use:+-- > naryOp2_ o x y = unsafeNaryOp_ o [x,y]+naryOp2_+    :: (ABT Term abt) => NaryOp a -> abt '[] a -> abt '[] a -> abt '[] a+naryOp2_ o x y =+    case (matchNaryOp o x, matchNaryOp o y) of+    (Just xs, Just ys) -> syn . NaryOp_ o $ xs Seq.>< ys+    (Just xs, Nothing) -> syn . NaryOp_ o $ xs Seq.|> y+    (Nothing, Just ys) -> syn . NaryOp_ o $ x  Seq.<| ys+    (Nothing, Nothing) -> syn . NaryOp_ o $ x  Seq.<| Seq.singleton y+++matchNaryOp+    :: (ABT Term abt) => NaryOp a -> abt '[] a -> Maybe (Seq (abt '[] a))+matchNaryOp o e =+    caseVarSyn e+        (const Nothing)+        $ \t ->+            case t of+            NaryOp_ o' xs | o' Prelude.== o -> Just xs+            _ -> Nothing+++----------------------------------------------------------------+----------------------------------------------------------------+----- Now for the actual EDSL++{-+infixr 9 `pair`++infixr 1 =<<+infixr 1 <=<, >=>+infixr 9 .+infixr 0 $+-}++infixl 1 >>=, >>+infixr 2 ||+infixr 3 &&+infix  4 ==, /=, <, <=, >, >=+infixl 4 <$>, <*>, <*, *> -- <$+infixl 6 +, -+infixl 7 *, /+infixr 8 ^, ^^, **+-- infixl9 is the default when things are unspecified+infixl 9 !, `app`, `thRootOf`++-- TODO: some infix notation reminiscent of \"::\"+-- TODO: actually do something with the type argument?+ann_ :: (ABT Term abt) => Sing a -> abt '[] a -> abt '[] a+ann_ _ e = e++coerceTo_ :: (ABT Term abt) => Coercion a b -> abt '[] a -> abt '[] b+coerceTo_ CNil e = e+coerceTo_ c    e = syn (CoerceTo_ c :$ e :* End)++unsafeFrom_ :: (ABT Term abt) => Coercion a b -> abt '[] b -> abt '[] a+unsafeFrom_ CNil e = e+unsafeFrom_ c    e = syn (UnsafeFrom_ c :$ e :* End)++literal_ :: (ABT Term abt) => Literal a  -> abt '[] a+literal_ = syn . Literal_+bool_    :: (ABT Term abt) => Bool     -> abt '[] HBool+bool_    = datum_ . (\b -> if b then dTrue else dFalse)+nat_     :: (ABT Term abt) => Natural  -> abt '[] 'HNat+nat_     = literal_ . LNat+int_     :: (ABT Term abt) => Integer  -> abt '[] 'HInt+int_     = literal_ . LInt+prob_    :: (ABT Term abt) => NonNegativeRational -> abt '[] 'HProb+prob_    = literal_ . LProb+real_    :: (ABT Term abt) => Rational -> abt '[] 'HReal+real_    = literal_ . LReal++fromRational+    :: forall abt a+    . (ABT Term abt, HFractional_ a)+    => Rational+    -> abt '[] a+fromRational =+    case (hFractional :: HFractional a) of+    HFractional_Prob -> prob_ . unsafeNonNegativeRational+    HFractional_Real -> real_++half :: forall abt a+     .  (ABT Term abt, HFractional_ a) => abt '[] a+half = fromRational (1 Prelude./ 2)++third :: (ABT Term abt, HFractional_ a) => abt '[] a+third = fromRational (1 Prelude./ 3)+++-- Boolean operators+true, false :: (ABT Term abt) => abt '[] HBool+true  = bool_ True+false = bool_ False++-- TODO: simplifications: distribution, constant-propogation+-- TODO: do we really want to distribute /by default/? Clearly we'll want to do that in some optimization\/partial-evaluation pass, but do note that it makes terms larger in general...+not :: (ABT Term abt) => abt '[] HBool -> abt '[] HBool+not e =+    Prelude.maybe (primOp1_ Not e) id+        $ caseVarSyn e+            (const Nothing)+            $ \t ->+                case t of+                PrimOp_ Not :$ es' ->+                    case es' of+                    e' :* End -> Just e'+                    _         -> error "not: the impossible happened"+                NaryOp_ And xs ->+                    Just . syn . NaryOp_ Or  $ Prelude.fmap not xs+                NaryOp_ Or xs ->+                    Just . syn . NaryOp_ And $ Prelude.fmap not xs+                NaryOp_ Xor xs ->+                    Just . syn . NaryOp_ Iff $ Prelude.fmap not xs+                NaryOp_ Iff xs ->+                    Just . syn . NaryOp_ Xor $ Prelude.fmap not xs+                Literal_ _ -> error "not: the impossible happened"+                _ -> Nothing++and, or :: (ABT Term abt) => [abt '[] HBool] -> abt '[] HBool+and = naryOp_withIdentity And true+or  = naryOp_withIdentity Or  false++(&&), (||),+    -- (</=>), (<==>), (==>), (<==), (\\), (//) -- TODO: better names?+    nand, nor+    :: (ABT Term abt) => abt '[] HBool -> abt '[] HBool -> abt '[] HBool+(&&) = naryOp2_ And+(||) = naryOp2_ Or+-- (</=>) = naryOp2_ Xor+-- (<==>) = naryOp2_ Iff+-- (==>)  = primOp2_ Impl+-- (<==)  = flip (==>)+-- (\\)   = primOp2_ Diff+-- (//)   = flip (\\)+nand   = primOp2_ Nand+nor    = primOp2_ Nor+++-- HEq & HOrder operators+(==), (/=)+    :: (ABT Term abt, HEq_ a) => abt '[] a -> abt '[] a -> abt '[] HBool+(==) = primOp2_ $ Equal hEq+(/=) = (not .) . (==)++(<), (<=), (>), (>=)+    :: (ABT Term abt, HOrd_ a) => abt '[] a -> abt '[] a -> abt '[] HBool+(<)    = primOp2_ $ Less hOrd+x <= y = not (x > y) -- or: @(x < y) || (x == y)@+(>)    = flip (<)+(>=)   = flip (<=)++min, max :: (ABT Term abt, HOrd_ a) => abt '[] a -> abt '[] a -> abt '[] a+min = naryOp2_ $ Min hOrd+max = naryOp2_ $ Max hOrd++-- TODO: if @a@ is bounded, then we can make these safe...+minimum, maximum :: (ABT Term abt, HOrd_ a) => [abt '[] a] -> abt '[] a+minimum = unsafeNaryOp_ $ Min hOrd+maximum = unsafeNaryOp_ $ Max hOrd+++-- HSemiring operators+(+), (*)+    :: (ABT Term abt, HSemiring_ a) => abt '[] a -> abt '[] a -> abt '[] a+(+) = naryOp2_ $ Sum  hSemiring+(*) = naryOp2_ $ Prod hSemiring++zero, one :: forall abt a. (ABT Term abt, HSemiring_ a) => abt '[] a+zero = zero_ (hSemiring :: HSemiring a)+one  = one_  (hSemiring :: HSemiring a)++zero_, one_ :: (ABT Term abt) => HSemiring a -> abt '[] a+zero_ HSemiring_Nat  = literal_ $ LNat  0+zero_ HSemiring_Int  = literal_ $ LInt  0+zero_ HSemiring_Prob = literal_ $ LProb 0+zero_ HSemiring_Real = literal_ $ LReal 0+one_  HSemiring_Nat  = literal_ $ LNat  1+one_  HSemiring_Int  = literal_ $ LInt  1+one_  HSemiring_Prob = literal_ $ LProb 1+one_  HSemiring_Real = literal_ $ LReal 1++-- TODO: add a smart constructor for @HSemiring_ a => Natural -> abt '[] a@ and\/or @HRing_ a => Integer -> abt '[] a@++sum, prod :: (ABT Term abt, HSemiring_ a) => [abt '[] a] -> abt '[] a+sum  = naryOp_withIdentity (Sum  hSemiring) zero+prod = naryOp_withIdentity (Prod hSemiring) one++{-+sum, product :: (ABT Term abt, HSemiring_ a) => [abt '[] a] -> abt '[] a+sum     = unsafeNaryOp_ $ Sum  hSemiring+product = unsafeNaryOp_ $ Prod hSemiring+-}+++-- TODO: simplifications+(^) :: (ABT Term abt, HSemiring_ a)+    => abt '[] a -> abt '[] 'HNat -> abt '[] a+(^) = primOp2_ $ NatPow hSemiring++-- TODO: this is actually safe, how can we capture that?+-- TODO: is this type restruction actually helpful anywhere for us?+-- If so, we ought to make this function polymorphic so that we can+-- use it for non-HRing HSemirings too...+square :: (ABT Term abt, HRing_ a) => abt '[] a -> abt '[] (NonNegative a)+square e = unsafeFrom_ signed (e ^ nat_ 2)+++-- HRing operators+(-) :: (ABT Term abt, HRing_ a) => abt '[] a -> abt '[] a -> abt '[] a+x - y = x + negate y+++-- TODO: do we really want to distribute negation over addition /by+-- default/? Clearly we'll want to do that in some+-- optimization\/partial-evaluation pass, but do note that it makes+-- terms larger in general...+negate :: (ABT Term abt, HRing_ a) => abt '[] a -> abt '[] a+negate e =+    Prelude.maybe (primOp1_ (Negate hRing) e) id+        $ caseVarSyn e+            (const Nothing)+            $ \t ->+                case t of+                -- TODO: need we case analyze the @HSemiring@?+                NaryOp_ (Sum theSemi) xs ->+                    Just . syn . NaryOp_ (Sum theSemi) $ Prelude.fmap negate xs+                -- TODO: need we case analyze the @HRing@?+                PrimOp_ (Negate _theRing) :$ es' ->+                    case es' of+                    e' :* End -> Just e'+                    _         -> error "negate: the impossible happened"+                _ -> Nothing+++-- TODO: test case: @negative . square@ simplifies away the intermediate coercions. (cf., normal')+-- BUG: this can lead to ambiguity when used with the polymorphic functions of RealProb.+-- | An occasionally helpful variant of 'negate'.+negative :: (ABT Term abt, HRing_ a) => abt '[] (NonNegative a) -> abt '[] a+negative = negate . coerceTo_ signed+++abs :: (ABT Term abt, HRing_ a) => abt '[] a -> abt '[] a+abs = coerceTo_ signed . abs_++abs_ :: (ABT Term abt, HRing_ a) => abt '[] a -> abt '[] (NonNegative a)+abs_ e = +    Prelude.maybe (primOp1_ (Abs hRing) e) id+        $ caseVarSyn e+            (const Nothing)+            $ \t ->+                case t of+                -- BUG: can't use the 'Signed' pattern synonym here, because that /requires/ the input to be (NonNegative a), instead of giving us the information that it is.+                -- TODO: need we case analyze the @HRing@?+                CoerceTo_ (CCons (Signed _theRing) CNil) :$ es' ->+                    case es' of+                    e' :* End -> Just e'+                    _         -> error "abs_: the impossible happened"+                _ -> Nothing+++-- TODO: any obvious simplifications? idempotent?+signum :: (ABT Term abt, HRing_ a) => abt '[] a -> abt '[] a+signum = primOp1_ $ Signum hRing+++-- HFractional operators+(/) :: (ABT Term abt, HFractional_ a) => abt '[] a -> abt '[] a -> abt '[] a+x / y = x * recip y+++-- TODO: generalize this pattern so we don't have to repeat it...+--+-- TODO: do we really want to distribute reciprocal over multiplication+-- /by default/? Clearly we'll want to do that in some+-- optimization\/partial-evaluation pass, but do note that it makes+-- terms larger in general...+recip :: (ABT Term abt, HFractional_ a) => abt '[] a -> abt '[] a+recip e0 =+    Prelude.maybe (primOp1_ (Recip hFractional) e0) id+        $ caseVarSyn e0+            (const Nothing)+            $ \t0 ->+                case t0 of+                -- TODO: need we case analyze the @HSemiring@?+                NaryOp_ (Prod theSemi) xs ->+                    Just . syn . NaryOp_ (Prod theSemi) $ Prelude.fmap recip xs+                -- TODO: need we case analyze the @HFractional@?+                PrimOp_ (Recip _theFrac) :$ es' ->+                    case es' of+                    e :* End -> Just e+                    _ -> error "recip: the impossible happened"+                _ -> Nothing+++-- TODO: simplifications+-- TODO: a variant of 'if_' which gives us the evidence that the argument is non-negative, so we don't need to coerce or use 'abs_'+(^^) :: (ABT Term abt, HFractional_ a)+    => abt '[] a -> abt '[] 'HInt -> abt '[] a+x ^^ y =+    if_ (y < int_ 0)+        (recip x ^ abs_ y)+        (x ^ abs_ y)+++-- HRadical operators+-- N.B., HProb is the only HRadical type (for now...)+-- TODO: simplifications+thRootOf+    :: (ABT Term abt, HRadical_ a)+    => abt '[] 'HNat -> abt '[] a -> abt '[] a+n `thRootOf` x = primOp2_ (NatRoot hRadical) x n++sqrt :: (ABT Term abt, HRadical_ a) => abt '[] a -> abt '[] a+sqrt = (nat_ 2 `thRootOf`)++{-+-- TODO: simplifications+(^+) :: (ABT Term abt, HRadical_ a)+    => abt '[] a -> abt '[] 'HPositiveRational -> abt '[] a+x ^+ y = casePositiveRational y $ \n d -> d `thRootOf` (x ^ n)++(^*) :: (ABT Term abt, HRadical_ a)+    => abt '[] a -> abt '[] 'HRational -> abt '[] a+x ^* y = caseRational y $ \n d -> d `thRootOf` (x ^^ n)+-}++betaFunc+    :: (ABT Term abt) => abt '[] 'HProb -> abt '[] 'HProb -> abt '[] 'HProb+betaFunc = primOp2_ BetaFunc+++integrate+    :: (ABT Term abt)+    => abt '[] 'HReal+    -> abt '[] 'HReal+    -> (abt '[] 'HReal -> abt '[] 'HProb)+    -> abt '[] 'HProb+integrate lo hi f =+    syn (Integrate :$ lo :* hi :* binder Text.empty sing f :* End)++summate+    :: (ABT Term abt, HDiscrete_ a, HSemiring_ b, SingI a)+    => abt '[] a+    -> abt '[] a+    -> (abt '[] a -> abt '[] b)+    -> abt '[] b+summate lo hi f =+    syn (Summate hDiscrete hSemiring+         :$ lo :* hi :* binder Text.empty sing f :* End)++product+    :: (ABT Term abt, HDiscrete_ a, HSemiring_ b, SingI a)+    => abt '[] a+    -> abt '[] a+    -> (abt '[] a -> abt '[] b)+    -> abt '[] b+product lo hi f =+    syn (Product hDiscrete hSemiring+         :$ lo :* hi :* binder Text.empty sing f :* End)+++class Integrable (a :: Hakaru) where+    infinity :: (ABT Term abt) => abt '[] a++instance Integrable 'HNat where+    infinity = primOp0_ (Infinity HIntegrable_Nat)++instance Integrable 'HInt where+    infinity = nat2int $ primOp0_ (Infinity HIntegrable_Nat)++instance Integrable 'HProb where+    infinity = primOp0_ (Infinity HIntegrable_Prob)++instance Integrable 'HReal where+    infinity = fromProb $ primOp0_ (Infinity HIntegrable_Prob)++-- HACK: we define this class in order to gain more polymorphism;+-- but, will it cause type inferencing issues? Excepting 'log'+-- (which should be moved out of the class) these are all safe.+class RealProb (a :: Hakaru) where+    (**) :: (ABT Term abt) => abt '[] 'HProb -> abt '[] a -> abt '[] 'HProb+    exp  :: (ABT Term abt) => abt '[] a -> abt '[] 'HProb+    erf  :: (ABT Term abt) => abt '[] a -> abt '[] a+    pi   :: (ABT Term abt) => abt '[] a+    gammaFunc :: (ABT Term abt) => abt '[] a -> abt '[] 'HProb++instance RealProb 'HReal where+    (**)      = primOp2_ RealPow+    exp       = primOp1_ Exp+    erf       = primOp1_ $ Erf hContinuous+    pi        = fromProb $ primOp0_ Pi+    gammaFunc = primOp1_ GammaFunc++instance RealProb 'HProb where+    x ** y    = primOp2_ RealPow x $ fromProb y+    exp       = primOp1_ Exp . fromProb+    erf       = primOp1_ $ Erf hContinuous+    pi        = primOp0_ Pi+    gammaFunc = primOp1_ GammaFunc . fromProb++log  :: (ABT Term abt) => abt '[] 'HProb -> abt '[] 'HReal+log = primOp1_ Log++logBase+    :: (ABT Term abt)+    => abt '[] 'HProb+    -> abt '[] 'HProb+    -> abt '[] 'HReal+logBase b x = log x / log b -- undefined when b == 1++sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh+    :: (ABT Term abt) => abt '[] 'HReal -> abt '[] 'HReal+sin    = primOp1_ Sin+cos    = primOp1_ Cos+tan    = primOp1_ Tan+asin   = primOp1_ Asin+acos   = primOp1_ Acos+atan   = primOp1_ Atan+sinh   = primOp1_ Sinh+cosh   = primOp1_ Cosh+tanh   = primOp1_ Tanh+asinh  = primOp1_ Asinh+acosh  = primOp1_ Acosh+atanh  = primOp1_ Atanh+++----------------------------------------------------------------+datum_+    :: (ABT Term abt)+    => Datum (abt '[]) (HData' t)+    -> abt '[] (HData' t)+datum_ = syn . Datum_++case_+     :: (ABT Term abt)+     => abt '[] a+     -> [Branch a abt b]+     -> abt '[] b+case_ e bs = syn (Case_ e bs)++branch+    :: (ABT Term abt)+    => Pattern xs a+    -> abt xs b+    -> Branch a abt b+branch = Branch++unit :: (ABT Term abt) => abt '[] HUnit+unit = datum_ dUnit++pair+    :: (ABT Term abt, SingI a, SingI b)+    => abt '[] a -> abt '[] b -> abt '[] (HPair a b)+pair = (datum_ .) . dPair+++pair_+    :: (ABT Term abt)+    => Sing a+    -> Sing b+    -> abt '[] a+    -> abt '[] b+    -> abt '[] (HPair a b)+pair_ a b = (datum_ .) . dPair_ a b+++unpair+    :: forall abt a b c+    .  (ABT Term abt)+    => abt '[] (HPair a b)+    -> (abt '[] a -> abt '[] b -> abt '[] c)+    -> abt '[] c+unpair e hoas =+    let (aTyp,bTyp) = sUnPair $ typeOf e+        body        = hoas (var a) (var b)+        inc x       = 1 Prelude.+ x+        a           = Variable Text.empty (nextBind body)         aTyp+        b           = Variable Text.empty (inc . nextBind $ body) bTyp+    in case_ e+        [Branch (pPair PVar PVar)+           (bind a (bind b body))+        ]++fst :: (ABT Term abt)+    => abt '[] (HPair a b)+    -> abt '[] a+fst p = unpair p (\x _ -> x)++snd :: (ABT Term abt)+    => abt '[] (HPair a b)+    -> abt '[] b+snd p = unpair p (\_ y -> y)++swap :: (ABT Term abt, SingI a, SingI b)+    => abt '[] (HPair a b)+    -> abt '[] (HPair b a)+swap ab = unpair ab (flip pair)++left+    :: (ABT Term abt, SingI a, SingI b)+    => abt '[] a -> abt '[] (HEither a b)+left = datum_ . dLeft++right+    :: (ABT Term abt, SingI a, SingI b)+    => abt '[] b -> abt '[] (HEither a b)+right = datum_ . dRight++uneither+    :: (ABT Term abt)+    => abt '[] (HEither a b)+    -> (abt '[] a -> abt '[] c)+    -> (abt '[] b -> abt '[] c)+    -> abt '[] c+uneither e l r =+    let (a,b) = sUnEither $ typeOf e+    in case_ e+        [ Branch (pLeft  PVar) (binder Text.empty a l)+        , Branch (pRight PVar) (binder Text.empty b r)+        ]++if_ :: (ABT Term abt)+    => abt '[] HBool+    -> abt '[] a+    -> abt '[] a+    -> abt '[] a+if_ b t f =+    case_ b+     [ Branch pTrue  t+     , Branch pFalse f+     ]++nil :: (ABT Term abt, SingI a) => abt '[] (HList a)+nil = datum_ dNil++cons+    :: (ABT Term abt, SingI a)+    => abt '[] a -> abt '[] (HList a) -> abt '[] (HList a)+cons = (datum_ .) . dCons++list :: (ABT Term abt, SingI a) => [abt '[] a] -> abt '[] (HList a)+list = Prelude.foldr cons nil++nothing :: (ABT Term abt, SingI a) => abt '[] (HMaybe a)+nothing = datum_ dNothing++just :: (ABT Term abt, SingI a) => abt '[] a -> abt '[] (HMaybe a)+just = datum_ . dJust++maybe :: (ABT Term abt, SingI a) => Maybe (abt '[] a) -> abt '[] (HMaybe a)+maybe = Prelude.maybe nothing just++unmaybe+    :: (ABT Term abt)+    => abt '[] (HMaybe a)+    -> abt '[] b+    -> (abt '[] a -> abt '[] b)+    -> abt '[] b+unmaybe e n j = +    case_ e+     [ Branch pNothing     n+     , Branch (pJust PVar) (binder Text.empty (sUnMaybe $ typeOf e) j)+     ]++unsafeProb :: (ABT Term abt) => abt '[] 'HReal -> abt '[] 'HProb+unsafeProb = unsafeFrom_ signed++fromProb   :: (ABT Term abt) => abt '[] 'HProb -> abt '[] 'HReal+fromProb   = coerceTo_ signed++nat2int    :: (ABT Term abt) => abt '[] 'HNat -> abt '[] 'HInt+nat2int    = coerceTo_ signed++fromInt    :: (ABT Term abt) => abt '[] 'HInt  -> abt '[] 'HReal+fromInt    = coerceTo_ continuous++nat2prob   :: (ABT Term abt) => abt '[] 'HNat  -> abt '[] 'HProb+nat2prob   = coerceTo_ continuous++nat2real   :: (ABT Term abt) => abt '[] 'HNat  -> abt '[] 'HReal+nat2real   = coerceTo_ (continuous . signed)++{- -- Uncomment only if we actually end up needing this anywhere+class FromNat (a :: Hakaru) where+    fromNat :: (ABT Term abt) => abt '[] 'HNat  -> abt '[] a++instance FromNat 'HNat  where fromNat = id+instance FromNat 'HInt  where fromNat = nat2int+instance FromNat 'HProb where fromNat = nat2prob+instance FromNat 'HReal where fromNat = fromProb . nat2prob+-}++unsafeProbFraction+    :: forall abt a+    .  (ABT Term abt, HFractional_ a)+    => abt '[] a+    -> abt '[] 'HProb+unsafeProbFraction e =+    unsafeProbFraction_ (hFractional :: HFractional a) e++unsafeProbFraction_+    :: (ABT Term abt)+    => HFractional a+    -> abt '[] a+    -> abt '[] 'HProb+unsafeProbFraction_ HFractional_Prob = id+unsafeProbFraction_ HFractional_Real = unsafeProb++unsafeProbSemiring+    :: forall abt a+    .  (ABT Term abt, HSemiring_ a)+    => abt '[] a+    -> abt '[] 'HProb+unsafeProbSemiring e =+    unsafeProbSemiring_ (hSemiring :: HSemiring a) e++unsafeProbSemiring_+    :: (ABT Term abt)+    => HSemiring a+    -> abt '[] a+    -> abt '[] 'HProb+unsafeProbSemiring_ HSemiring_Nat  = nat2prob+unsafeProbSemiring_ HSemiring_Int  = coerceTo_ continuous . unsafeFrom_ signed+unsafeProbSemiring_ HSemiring_Prob = id+unsafeProbSemiring_ HSemiring_Real = unsafeProb+++negativeInfinity :: ( ABT Term abt+                    , HRing_ a+                    , Integrable a)+                 => abt '[] a+negativeInfinity = negate infinity++-- instance (ABT Term abt) => Lambda abt where+-- 'app' already defined++-- TODO: use 'typeOf' to remove the 'SingI' requirement somehow+-- | A variant of 'lamWithVar' for automatically computing the type+-- via 'sing'.+lam :: (ABT Term abt, SingI a)+    => (abt '[] a -> abt '[] b)+    -> abt '[] (a ':-> b)+lam = lamWithVar Text.empty sing++-- | Create a lambda abstraction. The first two arguments give the+-- hint and type of the lambda-bound variable in the result. If you+-- want to automatically fill those in, then see 'lam'.+lamWithVar+    :: (ABT Term abt)+    => Text.Text+    -> Sing a+    -> (abt '[] a -> abt '[] b)+    -> abt '[] (a ':-> b)+lamWithVar hint typ f = syn (Lam_ :$ binder hint typ f :* End)++{-+-- some test cases to make sure we tied-the-knot successfully:+> let+    lam :: (ABT Term abt)+        => String+        -> Sing a+        -> (abt '[] a -> abt '[] b)+        -> abt '[] (a ':-> b)+    lam name typ f = syn (Lam_ :$ binder name typ f :* End)+> lam "x" SInt (\x -> x) :: TrivialABT Term ('HInt ':-> 'HInt)+> lam "x" SInt (\x -> lam "y" SInt $ \y -> x < y) :: TrivialABT Term ('HInt ':-> 'HInt ':-> 'HBool)+-}++-- TODO: make this smarter so that if the @e@ is already a variable then we just plug it into @f@ instead of introducing the trivial let-binding.+let_+    :: (ABT Term abt)+    => abt '[] a+    -> (abt '[] a -> abt '[] b)+    -> abt '[] b+let_ e f = syn (Let_ :$ e :* binder Text.empty (typeOf e) f :* End)+++----------------------------------------------------------------+array+    :: (ABT Term abt)+    => abt '[] 'HNat+    -> (abt '[] 'HNat -> abt '[] a)+    -> abt '[] ('HArray a)+array n =+    syn . Array_ n . binder Text.empty sing++arrayWithVar+    :: (ABT Term abt)+    => abt '[] 'HNat+    -> Variable 'HNat+    -> abt '[] a+    -> abt '[] ('HArray a)+arrayWithVar n x body =+    syn $ Array_ n (bind x body)+++empty :: (ABT Term abt, SingI a) => abt '[] ('HArray a)+empty = syn (Empty_ sing)++(!) :: (ABT Term abt)+    => abt '[] ('HArray a) -> abt '[] 'HNat -> abt '[] a+(!) e = arrayOp2_ (Index . sUnArray $ typeOf e) e++size :: (ABT Term abt) => abt '[] ('HArray a) -> abt '[] 'HNat+size e = arrayOp1_ (Size . sUnArray $ typeOf e) e++reduce+    :: (ABT Term abt)+    => (abt '[] a -> abt '[] a -> abt '[] a)+    -> abt '[] a+    -> abt '[] ('HArray a)+    -> abt '[] a+reduce f e =+    let a  = typeOf e+        f' = lamWithVar Text.empty a $ \x ->+                lamWithVar Text.empty a $ \y -> f x y+    in arrayOp3_ (Reduce a) f' e++-- TODO: better names for all these. The \"V\" suffix doesn't make sense anymore since we're calling these arrays, not vectors...+-- TODO: bust these all out into their own place, since the API for arrays is gonna be huge++sumV :: (ABT Term abt, HSemiring_ a)+    => abt '[] ('HArray a) -> abt '[] a+sumV = reduce (+) zero -- equivalent to summateV if @a ~ 'HProb@++summateV :: (ABT Term abt) => abt '[] ('HArray 'HProb) -> abt '[] 'HProb+summateV x =+    summate (nat_ 0) (size x)+        (\i -> x ! i)++-- TODO: a variant of 'if_' for giving us evidence that the subtraction is sound.++unsafeMinusNat+    :: (ABT Term abt) => abt '[] 'HNat -> abt '[] 'HNat -> abt '[] 'HNat+unsafeMinusNat x y = unsafeFrom_ signed (nat2int x - nat2int y)++unsafeMinusProb+    :: (ABT Term abt) => abt '[] 'HProb -> abt '[] 'HProb -> abt '[] 'HProb+unsafeMinusProb x y = unsafeProb (fromProb x - fromProb y)++-- | For any semiring we can attempt subtraction by lifting to a+-- ring, subtracting there, and then lowering back to the semiring.+-- Of course, the lowering step may well fail.+unsafeMinus+    :: (ABT Term abt, HSemiring_ a) => abt '[] a -> abt '[] a -> abt '[] a+unsafeMinus = unsafeMinus_ hSemiring++-- | A variant of 'unsafeMinus' for explicitly passing the semiring+-- instance.+unsafeMinus_+    :: (ABT Term abt) => HSemiring a -> abt '[] a -> abt '[] a -> abt '[] a+unsafeMinus_ theSemi =+    signed_HSemiring theSemi $ \c ->+        let lift  = coerceTo_   c+            lower = unsafeFrom_ c+        in \e1 e2 -> lower (lift e1 - lift e2)++-- TODO: move to Coercion.hs?+-- | For any semiring, return a coercion to its ring completion.+-- Because this completion is existentially quantified, we must use+-- a cps trick to eliminate the existential.+signed_HSemiring+    :: HSemiring a -> (forall b. (HRing_ b) => Coercion a b -> r) -> r+signed_HSemiring c k =+    case c of+    HSemiring_Nat  -> k $ singletonCoercion (Signed HRing_Int)+    HSemiring_Int  -> k CNil+    HSemiring_Prob -> k $ singletonCoercion (Signed HRing_Real)+    HSemiring_Real -> k CNil++-- | For any semiring we can attempt division by lifting to a+-- semifield, dividing there, and then lowering back to the semiring.+-- Of course, the lowering step may well fail.+unsafeDiv+    :: (ABT Term abt, HSemiring_ a) => abt '[] a -> abt '[] a -> abt '[] a+unsafeDiv = unsafeDiv_ hSemiring++-- | A variant of 'unsafeDiv' for explicitly passing the semiring+-- instance.+unsafeDiv_+    :: (ABT Term abt) => HSemiring a -> abt '[] a -> abt '[] a -> abt '[] a+unsafeDiv_ theSemi =+    continuous_HSemiring theSemi $ \c ->+        let lift  = coerceTo_   c+            lower = unsafeFrom_ c+        in \e1 e2 -> lower (lift e1 / lift e2)++-- TODO: move to Coercion.hs?+-- | For any semiring, return a coercion to its semifield completion.+-- Because this completion is existentially quantified, we must use+-- a cps trick to eliminate the existential.+continuous_HSemiring+    :: HSemiring a -> (forall b. (HFractional_ b) => Coercion a b -> r) -> r+continuous_HSemiring c k =+    case c of+    HSemiring_Nat  -> k $ singletonCoercion (Continuous HContinuous_Prob)+    HSemiring_Int  -> k $ singletonCoercion (Continuous HContinuous_Real)+    HSemiring_Prob -> k CNil+    HSemiring_Real -> k CNil+++appendV+    :: (ABT Term abt)+    => abt '[] ('HArray a) -> abt '[] ('HArray a) -> abt '[] ('HArray a)+appendV v1 v2 =+    array (size v1 + size v2) $ \i ->+        if_ (i < size v1)+            (v1 ! i)+            (v2 ! (i `unsafeMinusNat` size v1))++mapWithIndex+    :: (ABT Term abt)+    => (abt '[] 'HNat -> abt '[] a -> abt '[] b)+    -> abt '[] ('HArray a)+    -> abt '[] ('HArray b)+mapWithIndex f v = array (size v) $ \i -> f i (v ! i)++mapV+    :: (ABT Term abt)+    => (abt '[] a -> abt '[] b)+    -> abt '[] ('HArray a)+    -> abt '[] ('HArray b)+mapV f v = array (size v) $ \i -> f (v ! i)++normalizeV+    :: (ABT Term abt)+    => abt '[] ('HArray 'HProb)+    -> abt '[] ('HArray 'HProb)+normalizeV x = mapV (/ sumV x) x++constV+    :: (ABT Term abt) => abt '[] 'HNat -> abt '[] b -> abt '[] ('HArray b)+constV n c = array n (const c)++unitV+    :: (ABT Term abt)+    => abt '[] 'HNat+    -> abt '[] 'HNat+    -> abt '[] ('HArray 'HProb)+unitV s i = array s (\j -> if_ (i == j) (prob_ 1) (prob_ 0))++zipWithV+    :: (ABT Term abt)+    => (abt '[] a -> abt '[] b -> abt '[] c)+    -> abt '[] ('HArray a)+    -> abt '[] ('HArray b)+    -> abt '[] ('HArray c)+zipWithV f v1 v2 =+    array (size v1) (\i -> f (v1 ! i) (v2 ! i))+++----------------------------------------------------------------+(>>=)+    :: (ABT Term abt)+    => abt '[] ('HMeasure a)+    -> (abt '[] a -> abt '[] ('HMeasure b))+    -> abt '[] ('HMeasure b)+m >>= f =+    syn (MBind :$ m+               :* binder Text.empty (sUnMeasure $ typeOf m) f+               :* End)+++dirac :: (ABT Term abt) => abt '[] a -> abt '[] ('HMeasure a)+dirac e1 = syn (Dirac :$ e1 :* End)+++-- TODO: can we use let-binding instead of (>>=)-binding (i.e., for when the dirac is immediately (>>=)-bound again...)?+(<$>)+    :: (ABT Term abt, SingI a)+    => (abt '[] a -> abt '[] b)+    -> abt '[] ('HMeasure a)+    -> abt '[] ('HMeasure b)+f <$> m = m >>= dirac . f++-- | N.B, this function may introduce administrative redexes.+-- Moreover, it's not clear that we should even allow the type+-- @'HMeasure (a ':-> b)@!+(<*>)+    :: (ABT Term abt, SingI a, SingI b)+    => abt '[] ('HMeasure (a ':-> b))+    -> abt '[] ('HMeasure a)+    -> abt '[] ('HMeasure b)+mf <*> mx = mf >>= \f -> app f <$> mx++-- TODO: ensure that @dirac a *> n@ simplifies to just @n@, regardless of @a@ but especially when @a = unit@.+(*>), (>>)+    :: (ABT Term abt, SingI a)+    => abt '[] ('HMeasure a)+    -> abt '[] ('HMeasure b)+    -> abt '[] ('HMeasure b)+m *> n = m >>= \_ -> n+(>>) = (*>)++-- TODO: ensure that @m <* dirac a@ simplifies to just @m@, regardless of @a@ but especially when @a = unit@.+(<*)+    :: (ABT Term abt, SingI a, SingI b)+    => abt '[] ('HMeasure a)+    -> abt '[] ('HMeasure b)+    -> abt '[] ('HMeasure a)+m <* n = m >>= \a -> n *> dirac a++bindx+    :: (ABT Term abt, SingI a, SingI b)+    => abt '[] ('HMeasure a)+    -> (abt '[] a -> abt '[] ('HMeasure b))+    -> abt '[] ('HMeasure (HPair a b))+m `bindx` f = m >>= \a -> pair a <$> f a++-- Defined because using @(<$>)@ and @(<*>)@ would introduce administrative redexes+liftM2+    :: (ABT Term abt, SingI a, SingI b)+    => (abt '[] a -> abt '[] b -> abt '[] c)+    -> abt '[] ('HMeasure a)+    -> abt '[] ('HMeasure b)+    -> abt '[] ('HMeasure c)+liftM2 f m n = m >>= \x -> f x <$> n+++lebesgue :: (ABT Term abt) => abt '[] ('HMeasure 'HReal)+lebesgue = measure0_ Lebesgue++counting :: (ABT Term abt) => abt '[] ('HMeasure 'HInt)+counting = measure0_ Counting++-- TODO: make this smarter by collapsing nested @Superpose_@ similar to how we collapse nested NaryOps. Though beware, that could cause duplication of the computation for the probabilities\/weights; thus may want to only do it when the weights are constant values, or \"simplify\" things by generating let-bindings in order to share work.+--+-- TODO: can we make this smarter enough to handle empty lists?+superpose+    :: (ABT Term abt)+    => NonEmpty (abt '[] 'HProb, abt '[] ('HMeasure a))+    -> abt '[] ('HMeasure a)+superpose = syn . Superpose_++-- | The empty measure. Is called @fail@ in the Core Hakaru paper.+reject+    :: (ABT Term abt)+    => (Sing ('HMeasure a))+    -> abt '[] ('HMeasure a)+reject = syn . Reject_++-- | The sum of two measures. Is called @mplus@ in the Core Hakaru paper.+(<|>) :: (ABT Term abt)+      => abt '[] ('HMeasure a)+      -> abt '[] ('HMeasure a)+      -> abt '[] ('HMeasure a)+x <|> y =+    superpose $+        case (matchSuperpose x, matchSuperpose y) of+        (Just xs, Just ys) -> xs <> ys+        (Just xs, Nothing) -> (one, y) :| L.toList xs -- HACK: reordering!+        (Nothing, Just ys) -> (one, x) :| L.toList ys+        (Nothing, Nothing) -> (one, x) :| [(one, y)]++matchSuperpose+    :: (ABT Term abt) +    => abt '[] ('HMeasure a)+    -> Maybe (NonEmpty (abt '[] 'HProb, abt '[] ('HMeasure a)))+matchSuperpose e =+    caseVarSyn e+        (const Nothing)+        $ \t ->+            case t of+            Superpose_ xs -> Just xs+            _ -> Nothing++-- TODO: we should ensure that the following reductions happen:+-- > (withWeight p m >> n) ---> withWeight p (m >> n)+-- > (m >> withWeight p n) ---> withWeight p (m >> n)+-- > withWeight 1 m ---> m+-- > withWeight p (withWeight q m) ---> withWeight (p*q) m+-- > (weight p >> m) ---> withWeight p m+--+-- | Adjust the weight of the current measure.+--+-- /N.B.,/ the name for this function is terribly inconsistent+-- across the literature, even just the Hakaru literature, let alone+-- the Hakaru code base. It is variously called \"factor\" or+-- \"weight\"; though \"factor\" is also used to mean the function+-- 'factor' or the function 'observe', and \"weight\" is also used+-- to mean the 'weight' function.+weight+    :: (ABT Term abt)+    => abt '[] 'HProb+    -> abt '[] ('HMeasure HUnit)+weight p = withWeight p (dirac unit)+++-- | A variant of 'weight' which removes an administrative @(dirac+-- unit >>)@ redex.+--+-- TODO: ideally we'll be able to get rid of this function entirely,+-- and be able to trust optimization to clean up any redexes+-- introduced by 'weight'.+withWeight+    :: (ABT Term abt)+    => abt '[] 'HProb+    -> abt '[] ('HMeasure w)+    -> abt '[] ('HMeasure w)+withWeight p m = syn $ Superpose_ ((p, m) :| [])+++-- | A particularly common use case of 'weight':+--+-- > weightedDirac e p+-- >     == weight p (dirac e)+-- >     == weight p *> dirac e+-- >     == dirac e <* weight p+weightedDirac+    :: (ABT Term abt, SingI a)+    => abt '[] a+    -> abt '[] 'HProb+    -> abt '[] ('HMeasure a)+weightedDirac e p = withWeight p (dirac e)+++-- TODO: this taking of two arguments is as per the Core Hakaru specification; but for the EDSL, can we rephrase this as just taking the first argument, using @dirac unit@ for the else-branch, and then, making @(>>)@ work in the right way to plug the continuation measure in place of the @dirac unit@.+-- TODO: would it help inference\/simplification at all to move this into the AST as a primitive? I mean, it is a primitive of Core Hakaru afterall... Also, that would help clarify whether the (first)argument should actually be an @HBool@ or whether it should be some sort of proposition.++-- | Assert that a condition is true.+--+-- /N.B.,/ the name for this function is terribly inconsistent+-- across the literature, even just the Hakaru literature, let alone+-- the Hakaru code base. It is variously called \"factor\" or+-- \"observe\"; though \"factor\" is also used to mean the function+-- 'pose', and \"observe\" is also used to mean the backwards part+-- of Lazy.hs.+guard+    :: (ABT Term abt)+    => abt '[] HBool+    -> abt '[] ('HMeasure HUnit)+guard b = withGuard b (dirac unit)+++-- | A variant of 'guard' which removes an administrative @(dirac+-- unit >>)@ redex.+--+-- TODO: ideally we'll be able to get rid of this function entirely,+-- and be able to trust optimization to clean up any redexes+-- introduced by 'guard'.+withGuard+    :: (ABT Term abt)+    => abt '[] HBool+    -> abt '[] ('HMeasure a)+    -> abt '[] ('HMeasure a)+withGuard b m = if_ b m (reject (typeOf m))+++densityCategorical+    :: (ABT Term abt)+    => abt '[] ('HArray 'HProb)+    -> abt '[] 'HNat+    -> abt '[] 'HProb+densityCategorical v i = v ! i / summateV v++categorical, categorical'+    :: (ABT Term abt)+    => abt '[] ('HArray 'HProb)+    -> abt '[] ('HMeasure 'HNat)+categorical = measure1_ Categorical++-- TODO: a variant of 'if_' which gives us the evidence that the argument is non-negative, so we don't need to coerce or use 'abs_'+categorical' v =+    counting >>= \i ->+    withGuard (int_ 0 <= i && i < nat2int (size v)) $+    let_ (unsafeFrom_ signed i) $ \i_ ->+    weightedDirac i_ (densityCategorical v i_)+++densityUniform+    :: (ABT Term abt)+    => abt '[] 'HReal+    -> abt '[] 'HReal+    -> abt '[] 'HReal+    -> abt '[] 'HProb+densityUniform lo hi _ = recip . unsafeProb $ hi - lo+++-- TODO: make Uniform polymorphic, so that if the two inputs are+-- HProb then we know the measure must be over HProb too+uniform, uniform'+    :: (ABT Term abt)+    => abt '[] 'HReal+    -> abt '[] 'HReal+    -> abt '[] ('HMeasure 'HReal)+uniform = measure2_ Uniform++uniform' lo hi = +    lebesgue >>= \x ->+    withGuard (lo < x && x < hi) $+        -- TODO: how can we capture that this 'unsafeProb' is safe? (and that this 'recip' isn't Infinity, for that matter)+    weightedDirac x (densityUniform lo hi x)++densityNormal+    :: (ABT Term abt)+    => abt '[] 'HReal+    -> abt '[] 'HProb+    -> abt '[] 'HReal+    -> abt '[] 'HProb+densityNormal mu sd x = +    exp (negate ((x - mu) ^ nat_ 2)  -- TODO: use negative\/square instead of negate\/(^2)+         / fromProb (prob_ 2 * sd ^ nat_ 2)) -- TODO: use square?+     / sd / sqrt (prob_ 2 * pi)+++normal, normal'+    :: (ABT Term abt)+    => abt '[] 'HReal+    -> abt '[] 'HProb+    -> abt '[] ('HMeasure 'HReal)+normal = measure2_ Normal++normal' mu sd  = +    lebesgue >>= \x ->+    weightedDirac x (densityNormal mu sd x)+++densityPoisson+    :: (ABT Term abt)+    => abt '[] 'HProb+    -> abt '[] 'HNat+    -> abt '[] 'HProb+densityPoisson l x =+     l ^ x+       / gammaFunc (nat2real (x + nat_ 1)) -- TODO: use factorial instead of gammaFunc...+       / exp l+++poisson, poisson'+    :: (ABT Term abt) => abt '[] 'HProb -> abt '[] ('HMeasure 'HNat)+poisson = measure1_ Poisson++poisson' l = +    counting >>= \x ->+    -- TODO: use 'SafeFrom_' instead of @if_ (x >= int_ 0)@ so we can prove that @unsafeFrom_ signed x@ is actually always safe.+    withGuard (int_ 0 <= x && prob_ 0 < l) $ -- N.B., @0 < l@ means simply that @l /= 0@; why phrase it the other way?+    let_ (unsafeFrom_ signed x) $ \x_ ->+        weightedDirac x_ (densityPoisson l x_)++densityGamma+    :: (ABT Term abt)+    => abt '[] 'HProb+    -> abt '[] 'HProb+    -> abt '[] 'HProb+    -> abt '[] 'HProb+densityGamma shape scale x =+    x ** (fromProb shape - real_ 1)+    * exp (negate . fromProb $ x / scale)+    / (scale ** shape * gammaFunc shape)+++gamma, gamma'+    :: (ABT Term abt)+    => abt '[] 'HProb+    -> abt '[] 'HProb+    -> abt '[] ('HMeasure 'HProb)+gamma = measure2_ Gamma++gamma' shape scale =+    lebesgue >>= \x ->+    -- TODO: use 'SafeFrom_' instead of @if_ (real_ 0 < x)@ so we can prove that @unsafeProb x@ is actually always safe. Of course, then we'll need to mess around with checking (/=0) which'll get ugly... Use another SafeFrom_ with an associated NonZero type?+    withGuard (real_ 0 < x) $+    let_ (unsafeProb x) $ \ x_ ->+    weightedDirac x_ (densityGamma shape scale x_)++densityBeta+    :: (ABT Term abt)+    => abt '[] 'HProb+    -> abt '[] 'HProb+    -> abt '[] 'HProb+    -> abt '[] 'HProb+densityBeta a b x =+    x ** (fromProb a - real_ 1)+    * unsafeProb (real_ 1 - fromProb x) ** (fromProb b - real_ 1)+    / betaFunc a b++beta, beta', beta''+    :: (ABT Term abt)+    => abt '[] 'HProb+    -> abt '[] 'HProb+    -> abt '[] ('HMeasure 'HProb)+beta = measure2_ Beta++beta' a b =+    -- TODO: make Uniform polymorphic, so that if the two inputs are HProb then we know the measure must be over HProb too, and hence @unsafeProb x@ must always be safe. Alas, capturing the safety of @unsafeProb (1-x)@ would take a lot more work...+    unsafeProb <$> uniform (real_ 0) (real_ 1) >>= \x ->+    weightedDirac x (densityBeta a b x)++beta'' a b =+    gamma a (prob_ 1) >>= \x ->+    gamma b (prob_ 1) >>= \y ->+    dirac (x / (x+y))++plateWithVar+    :: (ABT Term abt)+    => abt '[] 'HNat+    -> Variable 'HNat+    -> abt '[] ('HMeasure a)+    -> abt '[] ('HMeasure ('HArray a))+plateWithVar e1 x e2 = syn (Plate :$ e1 :* bind x e2 :* End)+        +plate :: (ABT Term abt)+      => abt '[] 'HNat+      -> (abt '[] 'HNat -> abt '[] ('HMeasure a))+      -> abt '[] ('HMeasure ('HArray a))+plate e f = syn (Plate :$ e :* binder Text.empty sing f :* End)++plate'+    :: (ABT Term abt, SingI a)+    => abt '[] ('HArray ('HMeasure          a))+    -> abt '[] (         'HMeasure ('HArray a))++plate' v = reduce r z (mapV m v)+    where+    r   = liftM2 appendV+    z   = dirac empty+    m a = (array (nat_ 1) . const) <$> a+++-- BUG: remove the 'SingI' requirement!+chain :: (ABT Term abt, SingI s)+      => abt '[] 'HNat+      -> abt '[] s+      -> (abt '[] s -> abt '[] ('HMeasure (HPair a s)))+      -> abt '[] ('HMeasure (HPair ('HArray a) s))+chain n s f = syn (Chain :$ n :* s :* binder Text.empty sing f :* End)++chain'+    :: (ABT Term abt, SingI s, SingI a)+    => abt '[] ('HArray (s ':-> 'HMeasure (HPair a s)))+    -> abt '[] s+    -> abt '[] ('HMeasure (HPair ('HArray a) s))++chain' v s0 = reduce r z (mapV m v) `app` s0+    where+    r x y = lam $ \s ->+            app x s >>= \v1s1 ->+            v1s1 `unpair` \v1 s1 ->+            app y s1 >>= \v2s2 ->+            v2s2 `unpair` \v2 s2 ->+            dirac $ pair (appendV v1 v2) s2+    z     = lam $ \s -> dirac (pair empty s)+    m a   = lam $ \s -> (`unpair` pair . array (nat_ 1) . const) <$> app a s+++invgamma+    :: (ABT Term abt)+    => abt '[] 'HProb+    -> abt '[] 'HProb+    -> abt '[] ('HMeasure 'HProb)+invgamma k t = recip <$> gamma k (recip t)++exponential+    :: (ABT Term abt) => abt '[] 'HProb -> abt '[] ('HMeasure 'HProb)+exponential = gamma (prob_ 1)++chi2 :: (ABT Term abt) => abt '[] 'HProb -> abt '[] ('HMeasure 'HProb)+chi2 v = gamma (v / prob_ 2) (prob_ 2)++cauchy+    :: (ABT Term abt)+    => abt '[] 'HReal+    -> abt '[] 'HProb+    -> abt '[] ('HMeasure 'HReal)+cauchy loc scale =+    normal (real_ 0) (prob_ 1) >>= \x ->+    normal (real_ 0) (prob_ 1) >>= \y ->+    dirac $ loc + fromProb scale * x / y++laplace+    :: (ABT Term abt)+    => abt '[] 'HReal+    -> abt '[] 'HProb+    -> abt '[] ('HMeasure 'HReal)+laplace loc scale =+    exponential (prob_ 1) >>= \v ->+    normal (real_ 0) (prob_ 1) >>= \z ->+    dirac $ loc + z * fromProb (scale * sqrt (prob_ 2 * v))++studentT+    :: (ABT Term abt)+    => abt '[] 'HReal+    -> abt '[] 'HProb+    -> abt '[] 'HProb+    -> abt '[] ('HMeasure 'HReal)+studentT loc scale v =+    normal loc scale >>= \z ->+    chi2 v >>= \df ->+    dirac $ z * fromProb (sqrt (v / df))++weibull+    :: (ABT Term abt)+    => abt '[] 'HProb+    -> abt '[] 'HProb+    -> abt '[] ('HMeasure 'HProb)+weibull b k =+    exponential (prob_ 1) >>= \x ->+    dirac $ b * x ** recip k++-- BUG: would it be better to 'observe' that @p <= 1@ before doing the superpose? At least that way things would be /defined/ for all inputs...+bern :: (ABT Term abt) => abt '[] 'HProb -> abt '[] ('HMeasure HBool)+bern p = weightedDirac true  p+     <|> weightedDirac false (prob_ 1 `unsafeMinusProb` p)++mix :: (ABT Term abt)+    => abt '[] ('HArray 'HProb) -> abt '[] ('HMeasure 'HNat)+mix v = withWeight (sumV v) (categorical v)++binomial+    :: (ABT Term abt)+    => abt '[] 'HNat+    -> abt '[] 'HProb+    -> abt '[] ('HMeasure 'HInt)+binomial n p =+    sumV <$> plate n (const $ ((\b -> if_ b (int_ 1) (int_ 0)) <$> bern p))++-- BUG: would it be better to 'observe' that @p >= 1@ before doing everything? At least that way things would be /defined/ for all inputs...+negativeBinomial+    :: (ABT Term abt)+    => abt '[] 'HNat+    -> abt '[] 'HProb -- N.B., must actually be between 0 and 1+    -> abt '[] ('HMeasure 'HNat)+negativeBinomial r p =+    gamma (nat2prob r) (recip (recip p `unsafeMinusProb` prob_ 1)) >>= poisson++geometric :: (ABT Term abt) => abt '[] 'HProb -> abt '[] ('HMeasure 'HNat)+geometric = negativeBinomial (nat_ 1)+++multinomial+    :: (ABT Term abt)+    => abt '[] 'HNat+    -> abt '[] ('HArray 'HProb)+    -> abt '[] ('HMeasure ('HArray 'HProb))+multinomial n v =+    reduce (liftM2 (zipWithV (+)))+        (dirac (constV (size v) (prob_ 0)))+        (constV n (unitV (size v) <$> categorical v))++dirichlet+    :: (ABT Term abt)+    => abt '[] ('HArray 'HProb)+    -> abt '[] ('HMeasure ('HArray 'HProb))+dirichlet a = normalizeV <$> plate (size a) (\ i -> a ! i  `gamma` prob_ 1)++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Syntax/TypeCheck.hs view
@@ -0,0 +1,1670 @@+{-# LANGUAGE CPP+           , ScopedTypeVariables+           , GADTs+           , DataKinds+           , KindSignatures+           , GeneralizedNewtypeDeriving+           , TypeOperators+           , FlexibleContexts+           , FlexibleInstances+           , OverloadedStrings+           , PatternGuards+           , Rank2Types+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.05.28+-- |+-- Module      :  Language.Hakaru.Syntax.TypeCheck+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- Bidirectional type checking for our AST.+----------------------------------------------------------------+module Language.Hakaru.Syntax.TypeCheck+    (+    -- * The type checking monad+      TypeCheckError+    , TypeCheckMonad(), runTCM, unTCM+    , TypeCheckMode(..)+    -- * Type checking itself+    , inferable+    , mustCheck+    , TypedAST(..)+    , inferType+    , checkType+    ) where++import           Prelude hiding (id, (.))+import           Control.Category+import           Data.Proxy            (KProxy(..))+import           Data.Text             (pack, Text())+import qualified Data.IntMap           as IM+import qualified Data.Traversable      as T+import qualified Data.List.NonEmpty    as L+import qualified Data.Foldable         as F+import qualified Data.Sequence         as S+import qualified Data.Vector           as V+#if __GLASGOW_HASKELL__ < 710+import           Control.Applicative   (Applicative(..), (<$>))+import           Data.Monoid           (Monoid(..))+#endif+import qualified Language.Hakaru.Parser.AST as U++import Data.Number.Nat                (fromNat)+import Language.Hakaru.Syntax.IClasses+import Language.Hakaru.Types.DataKind (Hakaru(..), HData', HBool)+import Language.Hakaru.Types.Sing+import Language.Hakaru.Types.Coercion+import Language.Hakaru.Types.HClasses+    ( HEq, hEq_Sing, HOrd, hOrd_Sing, HSemiring, hSemiring_Sing+    , hRing_Sing, sing_HRing, hFractional_Sing, sing_HFractional+    , sing_NonNegative, hDiscrete_Sing+    , HIntegrable(..)+    , HRadical(..), HContinuous(..))+import Language.Hakaru.Syntax.ABT+import Language.Hakaru.Syntax.Datum+import Language.Hakaru.Syntax.AST+import Language.Hakaru.Syntax.AST.Sing+    (sing_Literal, sing_MeasureOp)++----------------------------------------------------------------+----------------------------------------------------------------++-- | Those terms from which we can synthesize a unique type. We are+-- also allowed to check them, via the change-of-direction rule.+inferable :: U.AST -> Bool+inferable = not . mustCheck+++-- | Those terms whose types must be checked analytically. We cannot+-- synthesize (unambiguous) types for these terms.+--+-- N.B., this function assumes we're in 'StrictMode'. If we're+-- actually in 'LaxMode' then a handful of AST nodes behave+-- differently: in particular, 'U.NaryOp_', 'U.Superpose', and+-- 'U.Case_'. In strict mode those cases can just infer one of their+-- arguments and then check the rest against the inferred type.+-- (For case-expressions, we must also check the scrutinee since+-- it's type cannot be unambiguously inferred from the patterns.)+-- Whereas in lax mode we must infer all arguments and then take+-- the lub of their types in order to know which coercions to+-- introduce.+mustCheck :: U.AST -> Bool+mustCheck e = caseVarSyn e (const False) go+    where+    go :: U.MetaTerm -> Bool+    go (U.Lam_ _  e2)     = mustCheck' e2++    -- In general, applications don't require checking; we infer+    -- the first applicand to get the type of the second and of the+    -- result, then we check the second and return the result type.+    -- Thus, applications will only yield \"must check\" errors if+    -- the function does; but that's the responsability of the+    -- function term, not of the application term it's embedded+    -- within.+    --+    -- However, do note that the above only applies to lambda-defined+    -- functions, not to all \"function-like\" things. In particular,+    -- data constructors require checking (see the note below).+    go (U.App_ _  _)      = False++    -- We follow Dunfield & Pientka and \Pi\Sigma in inferring or+    -- checking depending on what the body requires. This is as+    -- opposed to the TLDI'05 paper, which always infers @e2@ but+    -- will check or infer the @e1@ depending on whether it has a+    -- type annotation or not.+    go (U.Let_ _ e2)      = mustCheck' e2++    go (U.Ann_ _ _)       = False+    go (U.CoerceTo_ _ _)  = False+    go (U.UnsafeTo_ _ _)  = False++    -- In general (according to Dunfield & Pientka), we should be+    -- able to infer the result of a fully saturated primop by+    -- looking up it's type and then checking all the arguments.+    go (U.PrimOp_  _ _)   = False+    go (U.ArrayOp_ _ es)  = F.all mustCheck es++    -- In strict mode: if we can infer any of the arguments, then+    -- we can check all the rest at the same type.+    --+    -- BUG: in lax mode we must be able to infer all of them;+    -- otherwise we may not be able to take the lub of the types+    go (U.NaryOp_   _ es) = F.all mustCheck es+    go (U.Superpose_ pes) = F.all (mustCheck . snd) pes++    -- Our numeric literals aren't polymorphic, so we can infer+    -- them just fine. Or rather, according to our AST they aren't;+    -- in truth, they are in the surface language. Which is part+    -- of the reason for needing 'LaxMode'+    --+    -- TODO: correctly capture our surface-language semantics by+    -- always treating literals as if we're in 'LaxMode'.+    go (U.Literal_ _) = False++    -- I return true because most folks (neelk, Pfenning, Dunfield+    -- & Pientka) say all data constructors mustCheck. The main+    -- issue here is dealing with (polymorphic) sum types and phantom+    -- types, since these mean the term doesn't contain enough+    -- information for all the type indices. Even for record types,+    -- there's the additional issue of the term (perhaps) not giving+    -- enough information about the nominal type even if it does+    -- give enough info for the structural type.+    --+    -- Still, given those limitations, we should be able to infer+    -- a subset of data constructors which happen to avoid the+    -- problem areas. In particular, given that our surface syntax+    -- doesn't use the sum-of-products representation, we should+    -- be able to rely on symbol resolution to avoid the nominal+    -- typing issue. Thus, for non-empty arrays and non-phantom+    -- record types, we should be able to infer the whole type+    -- provided we can infer the various subterms.+    go U.Empty_          = True+    go (U.Pair_ e1 e2)   = mustCheck  e1 && mustCheck e2+    go (U.Array_ _ e1)   = mustCheck' e1+    go (U.Datum_ _)      = True++    -- TODO: everyone says this, but it seems to me that if we can+    -- infer any of the branches (and check the rest to agree) then+    -- we should be able to infer the whole thing... Or maybe the+    -- problem is that the change-of-direction rule might send us+    -- down the wrong path?+    go (U.Case_ _ _)     = True++    go (U.Dirac_  e1)        = mustCheck  e1+    go (U.MBind_  _   e2)    = mustCheck' e2+    go (U.Plate_  _   e2)    = mustCheck' e2+    go (U.Chain_  _   e2 e3) = mustCheck  e2 && mustCheck' e3+    go (U.MeasureOp_ _ _)    = False+    go (U.Integrate_  _ _ _) = False+    go (U.Summate_    _ _ _) = False+    go (U.Product_    _ _ _) = False+    go U.Reject_             = True+    go (U.Expect_ _ e2)      = mustCheck' e2+    go (U.Observe_  e1  _)   = mustCheck  e1++mustCheck'+    :: MetaABT U.SourceSpan U.Term '[ 'U.U ] 'U.U+    -> Bool+mustCheck' e = caseBind e $ \_ e' -> mustCheck e'++----------------------------------------------------------------+----------------------------------------------------------------++type Input = Maybe (V.Vector Text)++type Ctx = VarSet ('KProxy :: KProxy Hakaru)++data TypeCheckMode = StrictMode | LaxMode | UnsafeMode+    deriving (Read, Show)++type TypeCheckError = Text++newtype TypeCheckMonad a =+    TCM { unTCM :: Ctx+                -> Input+                -> TypeCheckMode+                -> Either TypeCheckError a }++runTCM :: TypeCheckMonad a -> Input -> TypeCheckMode -> Either TypeCheckError a+runTCM m = unTCM m emptyVarSet++instance Functor TypeCheckMonad where+    fmap f m = TCM $ \ctx input mode -> fmap f (unTCM m ctx input mode)++instance Applicative TypeCheckMonad where+    pure x    = TCM $ \_ _ _ -> Right x+    mf <*> mx = mf >>= \f -> fmap f mx++-- TODO: ensure this instance has the appropriate strictness+instance Monad TypeCheckMonad where+    return   = pure+    mx >>= k =+        TCM $ \ctx input mode ->+        unTCM mx ctx input mode >>= \x ->+        unTCM (k x) ctx input mode++{-+-- We could provide this instance, but there's no decent error+-- message to give for the 'empty' case that works in all circumstances.+-- Because we only would need this to define 'inferOneCheckOthers',+-- we inline the definition there instead.+instance Alternative TypeCheckMonad where+    empty   = failwith "Alternative.empty"+    x <|> y = TCM $ \ctx mode ->+        case unTCM x ctx mode of+        Left  _ -> unTCM y ctx mode+        Right e -> Right e+-}++showT :: Show a => a -> Text+showT = pack . show++show1T :: Show1 a => a (i :: Hakaru) -> Text+show1T = pack . show1+++-- | Return the mode in which we're checking\/inferring types.+getInput :: TypeCheckMonad Input+getInput = TCM $ \_ input _ -> Right input++-- | Return the mode in which we're checking\/inferring types.+getMode :: TypeCheckMonad TypeCheckMode+getMode = TCM $ \_ _ mode -> Right mode++-- | Extend the typing context, but only locally.+pushCtx+    :: Variable (a :: Hakaru)+    -> TypeCheckMonad b+    -> TypeCheckMonad b+pushCtx x (TCM m) = TCM (m . insertVarSet x)++getCtx :: TypeCheckMonad Ctx+getCtx = TCM $ \ctx _ _ -> Right ctx++failwith :: TypeCheckError -> TypeCheckMonad r+failwith e = TCM $ \_ _ _ -> Left e++failwith_ :: TypeCheckError -> TypeCheckMonad r+failwith_ = failwith++makeErrMsg+    :: Text+    -> Maybe U.SourceSpan+    -> Text+    -> TypeCheckMonad TypeCheckError+makeErrMsg header sourceSpan footer = do+  input_ <- getInput+  case (sourceSpan, input_) of+    (Just s, Just input) ->+          return $ mconcat [ header+                           , U.printSourceSpan s input+                           , footer+                           ]+    _                    ->+          return $ mconcat [ header, "\n", footer ]++-- | Fail with a type-mismatch error.+typeMismatch+    :: Maybe U.SourceSpan+    -> Either Text (Sing (a :: Hakaru))+    -> Either Text (Sing (b :: Hakaru))+    -> TypeCheckMonad r+typeMismatch s typ1 typ2 = failwith =<<+    makeErrMsg+     "Type Mismatch:\n\n"+     s+     (mconcat [ "expected "+              , msg1+              , ", found "+              , msg2+              ])+    where+    msg1 = case typ1 of { Left msg -> msg; Right typ -> show1T typ }+    msg2 = case typ2 of { Left msg -> msg; Right typ -> show1T typ }++missingInstance+    :: Text+    -> Sing (a :: Hakaru)+    -> Maybe U.SourceSpan+    -> TypeCheckMonad r+missingInstance clas typ s = failwith =<<+   makeErrMsg+    "Missing Instance: "+    s+    (mconcat $ ["No ", clas, " instance for type ", showT typ])++missingLub+    :: Sing (a :: Hakaru)+    -> Sing (b :: Hakaru)+    -> Maybe U.SourceSpan+    -> TypeCheckMonad r+missingLub typ1 typ2 s = failwith =<<+    makeErrMsg+     "Missing common type:\n\n"+     s+     (mconcat ["No lub of types ", showT typ1, " and ", showT typ2])++-- we can't have free variables, so it must be a typo+ambiguousFreeVariable+    :: Text+    -> Maybe U.SourceSpan+    -> TypeCheckMonad r+ambiguousFreeVariable x s = failwith =<<+    makeErrMsg+     (mconcat $ ["Name not in scope: ", x])+     s+     " perhaps it is a typo?"++ambiguousNullCoercion+    :: Maybe U.SourceSpan+    -> TypeCheckMonad r+ambiguousNullCoercion s = failwith =<<+    makeErrMsg+     "Cannot infer type for null-coercion over a checking term."+     s+     "Please add a type annotation to either the term being coerced or the result of the coercion."++ambiguousEmptyNary+    :: Maybe U.SourceSpan+    -> TypeCheckMonad r+ambiguousEmptyNary s = failwith =<<+    makeErrMsg+     "Cannot infer unambiguous type for empty n-ary operator."+     s+     "Try adding an annotation on the result of the operator."++ambiguousMustCheckNary+    :: Maybe U.SourceSpan+    -> TypeCheckMonad r+ambiguousMustCheckNary s = failwith =<<+    makeErrMsg+     "Could not infer any of the arguments."+     s+     "Try adding a type annotation to at least one of them."++ambiguousMustCheck+    :: Maybe U.SourceSpan+    -> TypeCheckMonad r+ambiguousMustCheck s = failwith =<<+    makeErrMsg+     "Cannot infer types for checking terms."+     s+     "Please add a type annotation."++argumentNumberError+     :: TypeCheckMonad r+argumentNumberError = failwith =<<+    makeErrMsg "Argument error:" Nothing "Passed wrong number of arguments"++----------------------------------------------------------------+----------------------------------------------------------------+-- BUG: haddock doesn't like annotations on GADT constructors. So+-- here we'll avoid using the GADT syntax, even though it'd make+-- the data type declaration prettier\/cleaner.+-- <https://github.com/hakaru-dev/hakaru/issues/6>+--+-- | The @e' ∈ τ@ portion of the inference judgement.+data TypedAST (abt :: [Hakaru] -> Hakaru -> *)+    = forall b. TypedAST !(Sing b) !(abt '[] b)++instance Show2 abt => Show (TypedAST abt) where+    showsPrec p (TypedAST typ e) =+        showParen_12 p "TypedAST" typ e+++makeVar :: forall (a :: Hakaru). Variable 'U.U -> Sing a -> Variable a+makeVar (Variable hintID nameID _) typ =+    Variable hintID nameID typ+++inferBinder+    :: (ABT Term abt)+    => Sing a+    -> MetaABT U.SourceSpan U.Term '[ 'U.U ] 'U.U+    -> (forall b. Sing b -> abt '[ a ] b -> TypeCheckMonad r)+    -> TypeCheckMonad r+inferBinder typ e k =+    caseBind e $ \x e1 -> do+    let x' = x {varType = typ}+    TypedAST typ1 e1' <- pushCtx x' (inferType e1)+    k typ1 (bind x' e1')++inferBinders+    :: (ABT Term abt)+    => List1 Variable xs+    -> U.AST+    -> (forall a. Sing a -> abt xs a -> TypeCheckMonad r)+    -> TypeCheckMonad r+inferBinders = \xs e k -> do+    TypedAST typ e' <- pushesCtx xs (inferType e)+    k typ (binds_ xs e')+    where+    -- TODO: make sure the 'TCM'\/'unTCM' stuff doesn't do stupid asymptotic things+    pushesCtx+        :: List1 Variable (xs :: [Hakaru])+        -> TypeCheckMonad b+        -> TypeCheckMonad b+    pushesCtx Nil1         m = m+    pushesCtx (Cons1 x xs) m = pushesCtx xs (TCM (unTCM m . insertVarSet x))+++checkBinder+    :: (ABT Term abt)+    => Sing a+    -> Sing b+    -> MetaABT U.SourceSpan U.Term '[ 'U.U ] 'U.U+    -> TypeCheckMonad (abt '[ a ] b)+checkBinder typ eTyp e =+    caseBind e $ \x e1 -> do+    let x' = x {varType = typ}+    pushCtx x' (bind x' <$> checkType eTyp e1)+++checkBinders+    :: (ABT Term abt)+    => List1 Variable xs+    -> Sing a+    -> U.AST+    -> TypeCheckMonad (abt xs a)+checkBinders xs eTyp e =+    case xs of+    Nil1        -> checkType eTyp e+    Cons1 x xs' -> pushCtx x (bind x <$> checkBinders xs' eTyp e)+++----------------------------------------------------------------+-- | Given a typing environment and a term, synthesize the term's+-- type (and produce an elaborated term):+--+-- > Γ ⊢ e ⇒ e' ∈ τ+inferType+    :: forall abt+    .  (ABT Term abt)+    => U.AST+    -> TypeCheckMonad (TypedAST abt)+inferType = inferType_+  where+  -- HACK: we need to give these local definitions to avoid+  -- \"ambiguity\" in the choice of ABT instance...+  checkType_ :: forall b. Sing b -> U.AST -> TypeCheckMonad (abt '[] b)+  checkType_ = checkType++  inferOneCheckOthers_ ::+      [U.AST] -> TypeCheckMonad (TypedASTs abt)+  inferOneCheckOthers_ = inferOneCheckOthers+++  inferVariable+      :: Maybe U.SourceSpan+      -> Variable 'U.U+      -> TypeCheckMonad (TypedAST abt)+  inferVariable sourceSpan (Variable hintID nameID _) = do+      ctx <- getCtx+      case IM.lookup (fromNat nameID) (unVarSet ctx) of+        Just (SomeVariable x') ->+            return $ TypedAST (varType x') (var x')+        Nothing -> ambiguousFreeVariable hintID sourceSpan+++  -- HACK: We need this monomorphic binding so that GHC doesn't get+  -- confused about which @(ABT AST abt)@ instance to use in recursive+  -- calls.+  inferType_ :: U.AST -> TypeCheckMonad (TypedAST abt)+  inferType_ e0 =+    let s = getMetadata e0 in+    caseVarSyn e0 (inferVariable s) (go s)+    where+    go :: Maybe U.SourceSpan -> U.MetaTerm -> TypeCheckMonad (TypedAST abt)+    go sourceSpan t =+      case t of+       U.Lam_ (U.SSing typ) e -> do+           inferBinder typ e $ \typ2 e2 ->+               return . TypedAST (SFun typ typ2) $ syn (Lam_ :$ e2 :* End)++       U.App_ e1 e2 -> do+           TypedAST typ1 e1' <- inferType_ e1+           case typ1 of+               SFun typ2 typ3 -> do+                   e2' <- checkType_ typ2 e2+                   return . TypedAST typ3 $ syn (App_ :$ e1' :* e2' :* End)+               _ -> typeMismatch sourceSpan (Left "function type") (Right typ1)+           -- The above is the standard rule that everyone uses.+           -- However, if the @e1@ is a lambda (rather than a primop+           -- or a variable), then it will require a type annotation.+           -- Couldn't we just as well add an additional rule that+           -- says to infer @e2@ and then infer @e1@ under the assumption+           -- that the variable has the same type as the argument? (or+           -- generalize that idea to keep track of a bunch of arguments+           -- being passed in; sort of like a dual to our typing+           -- environments?) Is this at all related to what Dunfield+           -- & Neelk are doing in their ICFP'13 paper with that+           -- \"=>=>\" judgment? (prolly not, but...)++       U.Let_ e1 e2 -> do+           TypedAST typ1 e1' <- inferType_ e1+           inferBinder typ1 e2 $ \typ2 e2' ->+               return . TypedAST typ2 $ syn (Let_ :$ e1' :* e2' :* End)++       U.Ann_ (U.SSing typ1) e1 -> do+           -- N.B., this requires that @typ1@ is a 'Sing' not a 'Proxy',+           -- since we can't generate a 'Sing' from a 'Proxy'.+           TypedAST typ1 <$> checkType_ typ1 e1++       U.PrimOp_  op es -> inferPrimOp  op es+       U.ArrayOp_ op es -> inferArrayOp op es+       U.NaryOp_  op es -> do+           mode <- getMode+           TypedASTs typ es' <-+               case mode of+               StrictMode -> inferOneCheckOthers_ es+               LaxMode    -> inferLubType sourceSpan es+               UnsafeMode -> inferLubType sourceSpan es+           op' <- make_NaryOp typ op+           return . TypedAST typ $ syn (NaryOp_ op' $ S.fromList es')++       U.Literal_ (Some1 v) ->+           -- TODO: in truth, we can infer this to be any supertype+           -- (adjusting the concrete @v@ as necessary). That is, the+           -- surface language treats numeric literals as polymorphic,+           -- so we should capture that somehow--- even if we're not+           -- in 'LaxMode'. We'll prolly need to handle this+           -- subtype-polymorphism the same way as we do for for+           -- everything when in 'UnsafeMode'.+           return . TypedAST (sing_Literal v) $ syn (Literal_ v)++       -- TODO: we can try to do 'U.Case_' by using branch-based+       -- variants of 'inferOneCheckOthers' and 'inferLubType' depending+       -- on the mode; provided we can in fact infer the type of the+       -- scrutinee. N.B., if we add this case, then we need to update+       -- 'mustCheck' to return the right thing.++       U.CoerceTo_ (Some2 c) e1 ->+           case singCoerceDomCod c of+           Nothing+               | inferable e1 -> inferType_ e1+               | otherwise    -> ambiguousNullCoercion sourceSpan+           Just (dom,cod) -> do+               e1' <- checkType_ dom e1+               return . TypedAST cod $ syn (CoerceTo_ c :$ e1' :* End)++       U.UnsafeTo_ (Some2 c) e1 ->+           case singCoerceDomCod c of+           Nothing+               | inferable e1 -> inferType_ e1+               | otherwise    -> ambiguousNullCoercion sourceSpan+           Just (dom,cod) -> do+               e1' <- checkType_ cod e1+               return . TypedAST dom $ syn (UnsafeFrom_ c :$ e1' :* End)++       U.MeasureOp_ (U.SomeOp op) es -> do+           let (typs, typ1) = sing_MeasureOp op+           es' <- checkSArgs typs es+           return . TypedAST (SMeasure typ1) $ syn (MeasureOp_ op :$ es')++       U.Pair_ e1 e2 -> do+           TypedAST typ1 e1' <- inferType_ e1+           TypedAST typ2 e2' <- inferType_ e2+           return . TypedAST (sPair typ1 typ2) $+                  syn (Datum_ $ dPair_ typ1 typ2 e1' e2')++       U.Array_ e1 e2 -> do+           e1' <- checkType_ SNat e1+           inferBinder SNat e2 $ \typ2 e2' ->+               return . TypedAST (SArray typ2) $ syn (Array_ e1' e2')++       U.Case_ e1 branches -> do+           TypedAST typ1 e1' <- inferType_ e1+           mode <- getMode+           case mode of+               StrictMode -> inferCaseStrict typ1 e1' branches+               LaxMode    -> inferCaseLax sourceSpan typ1 e1' branches+               UnsafeMode -> inferCaseLax sourceSpan typ1 e1' branches++       U.Dirac_ e1 -> do+           TypedAST typ1 e1' <- inferType_ e1+           return . TypedAST (SMeasure typ1) $ syn (Dirac :$ e1' :* End)++       U.MBind_ e1 e2 ->+           caseBind e2 $ \x e2' -> do+           TypedAST typ1 e1' <- inferType_ e1+           case typ1 of+               SMeasure typ2 ->+                   let x' = makeVar x typ2 in+                   pushCtx x' $ do+                       TypedAST typ3 e3' <- inferType_ e2'+                       case typ3 of+                           SMeasure _ ->+                               return . TypedAST typ3 $+                                   syn (MBind :$ e1' :* bind x' e3' :* End)+                           _ -> typeMismatch sourceSpan (Left "HMeasure") (Right typ3)+                   {-+                   -- BUG: the \"ambiguous\" @abt@ issue again...+                   inferBinder typ2 e2 $ \typ3 e2' ->+                       case typ3 of+                       SMeasure _ -> return . TypedAST typ3 $+                           syn (MBind :$ e1' :* e2' :* End)+                       _ -> typeMismatch (Left "HMeasure") (Right typ3)+                   -}+               _ -> typeMismatch sourceSpan (Left "HMeasure") (Right typ1)++       U.Plate_ e1 e2 ->+           caseBind e2 $ \x e2' -> do+           e1' <- checkType_ SNat e1+           let x' = makeVar x SNat+           pushCtx x' $ do+               TypedAST typ2 e3' <- inferType_ e2'+               case typ2 of+                   SMeasure typ3 ->+                       return . TypedAST (SMeasure . SArray $ typ3) $+                              syn (Plate :$ e1' :* bind x' e3' :* End)+                   _ -> typeMismatch sourceSpan (Left "HMeasure") (Right typ2)++       U.Chain_ e1 e2 e3 ->+           caseBind e3 $ \x e3' -> do+           e1' <- checkType_ SNat e1+           TypedAST typ2 e2' <- inferType_ e2+           let x' = makeVar x typ2+           pushCtx x' $ do+               TypedAST typ3 e4' <- inferType_ e3'+               case typ3 of+                   SMeasure (SData (STyCon sym `STyApp` a `STyApp` b) _) ->+                       case (jmEq1 sym sSymbol_Pair, jmEq1 b typ2) of+                       (Just Refl, Just Refl) ->+                           return . TypedAST (SMeasure $ sPair (SArray a) typ2) $+                                  syn (Chain :$ e1' :* e2' :* bind x' e4' :* End)+                       _ -> typeMismatch sourceSpan (Left "HMeasure(HPair)") (Right typ3)+                   _     -> typeMismatch sourceSpan (Left "HMeasure(HPair)") (Right typ3)++       U.Integrate_ e1 e2 e3 -> do+           e1' <- checkType_ SReal e1+           e2' <- checkType_ SReal e2+           e3' <- checkBinder SReal SProb e3+           return . TypedAST SProb $+                  syn (Integrate :$ e1' :* e2' :* e3' :* End)++       U.Summate_ e1 e2 e3 -> do+           TypedAST typ1 e1' <- inferType e1+           e2' <- checkType_ typ1 e2+           inferBinder typ1 e3 $ \typ2 ee' ->+               case (hDiscrete_Sing typ1, hSemiring_Sing typ2) of+                 (Just h1, Just h2) ->+                     return . TypedAST typ2 $+                            syn (Summate h1 h2 :$ e1' :* e2' :* ee' :* End)+                 _                  -> failwith_ "Summate given bounds which are not discrete"++       U.Product_ e1 e2 e3 -> do+           TypedAST typ1 e1' <- inferType e1+           e2' <- checkType_ typ1 e2+           inferBinder typ1 e3 $ \typ2 e3' ->+               case (hDiscrete_Sing typ1, hSemiring_Sing typ2) of+                 (Just h1, Just h2) ->+                     return . TypedAST typ2 $+                            syn (Product h1 h2 :$ e1' :* e2' :* e3' :* End)+                 _                  -> failwith_ "Product given bounds which are not discrete"++       U.Expect_ e1 e2 -> do+           TypedAST typ1 e1' <- inferType_ e1+           case typ1 of+               SMeasure typ2 -> do+                   e2' <- checkBinder typ2 SProb e2+                   return . TypedAST SProb $ syn (Expect :$ e1' :* e2' :* End)+               _ -> typeMismatch sourceSpan (Left "HMeasure") (Right typ1)++       U.Observe_ e1 e2 -> do+           TypedAST typ1 e1' <- inferType_ e1+           case typ1 of+               SMeasure typ2 -> do+                   e2' <- checkType_ typ2 e2+                   return . TypedAST typ1 $ syn (Observe :$ e1' :* e2' :* End)+               _ -> typeMismatch sourceSpan (Left "HMeasure") (Right typ1)++       U.Superpose_ pes -> do+           -- TODO: clean up all this @map fst@, @map snd@, @zip@ stuff+           mode <- getMode+           TypedASTs typ es' <-+               case mode of+               StrictMode -> inferOneCheckOthers_    (L.toList $ fmap snd pes)+               LaxMode    -> inferLubType sourceSpan (L.toList $ fmap snd pes)+               UnsafeMode -> inferLubType sourceSpan (L.toList $ fmap snd pes)+           case typ of+               SMeasure _ -> do+                   ps' <- T.traverse (checkType SProb) (fmap fst pes)+                   return $ TypedAST typ (syn (Superpose_ (L.zip ps' (L.fromList es'))))+               _ -> typeMismatch sourceSpan (Left "HMeasure") (Right typ)++       _   | mustCheck e0 -> ambiguousMustCheck sourceSpan+           | otherwise    -> error "inferType: missing an inferable branch!"++  inferPrimOp+      :: U.PrimOp+      -> [U.AST]+      -> TypeCheckMonad (TypedAST abt)+  inferPrimOp U.Not es =+      case es of+        [e] -> do e' <- checkType_ sBool e+                  return . TypedAST sBool $ syn (PrimOp_ Not :$ e' :* End)+        _   -> argumentNumberError++  inferPrimOp U.Pi es =+      case es of+        [] -> return . TypedAST SProb $ syn (PrimOp_ Pi :$ End)+        _  -> argumentNumberError++  inferPrimOp U.Cos es =+      case es of+        [e] -> do e' <- checkType_ SReal e+                  return . TypedAST SReal $ syn (PrimOp_ Cos :$ e' :* End)+        _   -> argumentNumberError++  inferPrimOp U.RealPow es =+      case es of+        [e1, e2] -> do e1' <- checkType_ SProb e1+                       e2' <- checkType_ SReal e2+                       return . TypedAST SProb $+                              syn (PrimOp_ RealPow :$ e1' :* e2' :* End)+        _        -> argumentNumberError++  inferPrimOp U.Exp es =+      case es of+        [e] -> do e' <- checkType_ SReal e+                  return . TypedAST SProb $ syn (PrimOp_ Exp :$ e' :* End)+        _   -> argumentNumberError++  inferPrimOp U.Log es =+      case es of+        [e] -> do e' <- checkType_ SProb e+                  return . TypedAST SReal $ syn (PrimOp_ Log :$ e' :* End)+        _   -> argumentNumberError++  inferPrimOp U.Infinity es =+      case es of+        [] -> return . TypedAST SProb $+                     syn (PrimOp_ (Infinity HIntegrable_Prob) :$ End)+        _  -> argumentNumberError++  inferPrimOp U.GammaFunc es =+      case es of+        [e] -> do e' <- checkType_ SReal e+                  return . TypedAST SProb $ syn (PrimOp_ GammaFunc :$ e' :* End)+        _   -> argumentNumberError++  inferPrimOp U.BetaFunc es =+      case es of+        [e1, e2] -> do e1' <- checkType_ SProb e1+                       e2' <- checkType_ SProb e2+                       return . TypedAST SProb $+                              syn (PrimOp_ BetaFunc :$ e1' :* e2' :* End)+        _        -> argumentNumberError++  inferPrimOp U.Equal es =+      case es of+        [_, _] -> do mode <- getMode+                     TypedASTs typ [e1', e2'] <-+                         case mode of+                           StrictMode -> inferOneCheckOthers_ es+                           _          -> inferLubType Nothing es+                     primop <- Equal <$> getHEq typ+                     return . TypedAST sBool $+                            syn (PrimOp_ primop :$ e1' :* e2' :* End)+        _      -> argumentNumberError++  inferPrimOp U.Less es =+      case es of+        [_, _] -> do mode <- getMode+                     TypedASTs typ [e1', e2'] <-+                         case mode of+                           StrictMode -> inferOneCheckOthers_ es+                           _          -> inferLubType Nothing es+                     primop <- Less <$> getHOrd typ+                     return . TypedAST sBool $+                            syn (PrimOp_ primop :$ e1' :* e2' :* End)+        _      -> argumentNumberError++  inferPrimOp U.NatPow es =+      case es of+        [e1, e2] -> do TypedAST typ e1' <- inferType_ e1+                       e2' <- checkType_ SNat e2+                       primop <- NatPow <$> getHSemiring typ+                       return . TypedAST typ $+                              syn (PrimOp_ primop :$ e1' :* e2' :* End)+        _        -> argumentNumberError++  inferPrimOp U.Negate es =+      case es of+        [e] -> do TypedAST typ e' <- inferType_ e+                  mode <- getMode+                  SomeRing ring c <- getHRing typ mode+                  primop <- Negate <$> return ring+                  let e'' = case c of+                              CNil -> e'+                              c'   -> unLC_ . coerceTo c' $ LC_ e'+                  return . TypedAST (sing_HRing ring) $+                         syn (PrimOp_ primop :$ e'' :* End)+        _   -> argumentNumberError++  inferPrimOp U.Abs es =+      case es of+        [e] -> do TypedAST typ e' <- inferType_ e+                  mode <- getMode+                  SomeRing ring c <- getHRing typ mode+                  primop <- Abs <$> return ring+                  let e'' = case c of+                              CNil -> e'+                              c'   -> unLC_ . coerceTo c' $ LC_ e'+                  return . TypedAST (sing_NonNegative ring) $+                         syn (PrimOp_ primop :$ e'' :* End)+        _   -> argumentNumberError++  inferPrimOp U.Signum es =+      case es of+        [e] -> do TypedAST typ e' <- inferType_ e+                  mode <- getMode+                  SomeRing ring c <- getHRing typ mode+                  primop <- Signum <$> return ring+                  let e'' = case c of+                              CNil -> e'+                              c'   -> unLC_ . coerceTo c' $ LC_ e'+                  return . TypedAST (sing_HRing ring) $+                         syn (PrimOp_ primop :$ e'' :* End)+        _   -> argumentNumberError++  inferPrimOp U.Recip es =+      case es of+        [e] -> do TypedAST typ e' <- inferType_ e+                  mode <- getMode+                  SomeFractional frac c <- getHFractional typ mode+                  primop <- Recip <$> return frac+                  let e'' = case c of+                              CNil -> e'+                              c'   -> unLC_ . coerceTo c' $ LC_ e'+                  return . TypedAST (sing_HFractional frac) $+                         syn (PrimOp_ primop :$ e'' :* End)+        _   -> argumentNumberError++  -- BUG: Only defined for HRadical_Prob+  inferPrimOp U.NatRoot es =+      case es of+        [e1, e2] -> do e1' <- checkType_ SProb e1+                       e2' <- checkType_ SNat  e2+                       return . TypedAST SProb $+                              syn (PrimOp_ (NatRoot HRadical_Prob)+                                   :$ e1' :* e2' :* End)+        _   -> argumentNumberError++  -- BUG: Only defined for HContinuous_Real+  inferPrimOp U.Erf es =+      case es of+        [e] -> do e' <- checkType_ SReal e+                  return . TypedAST SReal $+                         syn (PrimOp_ (Erf HContinuous_Real)+                              :$ e' :* End)+        _   -> argumentNumberError++  inferPrimOp x es+      | Just y <- lookup x+                 [(U.Sin  , Sin  ),+                  (U.Cos  , Cos  ),+                  (U.Tan  , Tan  ),+                  (U.Asin , Asin ),+                  (U.Acos , Acos ),+                  (U.Atan , Atan ),+                  (U.Sinh , Sinh ),+                  (U.Cosh , Cosh ),+                  (U.Tanh , Tanh ),+                  (U.Asinh, Asinh),+                  (U.Acosh, Acosh),+                  (U.Atanh, Atanh)] =+      case es of+        [e] -> do e' <- checkType_ SReal e+                  return . TypedAST SReal $+                         syn (PrimOp_ y :$ e' :* End)+        _   -> argumentNumberError++  inferPrimOp x _ = error ("TODO: inferPrimOp: " ++ show x)+++  inferArrayOp :: U.ArrayOp+               -> [U.AST]+               -> TypeCheckMonad (TypedAST abt)+  inferArrayOp U.Index_ es =+      case es of+        [e1, e2] -> do TypedAST typ1 e1' <- inferType_ e1+                       case typ1 of+                         SArray typ2 -> do+                           e2' <- checkType_ SNat e2+                           return . TypedAST typ2 $+                                  syn (ArrayOp_ (Index typ2) :$ e1' :* e2' :* End)+                         _ -> typeMismatch Nothing (Left "HArray") (Right typ1)+        _        -> argumentNumberError++  inferArrayOp U.Size es =+      case es of+        [e] -> do TypedAST typ e' <- inferType_ e+                  case typ of+                    SArray typ1 -> do+                       return . TypedAST SNat $+                              syn (ArrayOp_ (Size typ1) :$ e' :* End)+                    _ -> typeMismatch Nothing (Left "HArray") (Right typ)+        _   -> argumentNumberError++  inferArrayOp U.Reduce es =+      case es of+        [e1, e2, e3] -> do+           TypedAST typ e1' <- inferType_ e1+           case typ of+             SFun typ1 typ2 -> do+               Refl <- jmEq1_ typ2 (SFun typ1 typ1)+               e2' <- checkType_ typ1 e2+               e3' <- checkType_ (SArray typ1) e3+               return . TypedAST typ1 $+                      syn (ArrayOp_ (Reduce typ1)+                           :$ e1' :* e2' :* e3' :* End)+             _ -> typeMismatch Nothing (Right typ) (Left "HFun")+        _            -> argumentNumberError++make_NaryOp :: Sing a -> U.NaryOp -> TypeCheckMonad (NaryOp a)+make_NaryOp a U.And  = isBool a >>= \Refl -> return And+make_NaryOp a U.Or   = isBool a >>= \Refl -> return Or+make_NaryOp a U.Xor  = isBool a >>= \Refl -> return Xor+make_NaryOp a U.Iff  = isBool a >>= \Refl -> return Iff+make_NaryOp a U.Min  = Min  <$> getHOrd a+make_NaryOp a U.Max  = Max  <$> getHOrd a+make_NaryOp a U.Sum  = Sum  <$> getHSemiring a+make_NaryOp a U.Prod = Prod <$> getHSemiring a++isBool :: Sing a -> TypeCheckMonad (TypeEq a HBool)+isBool typ =+    case jmEq1 typ sBool of+    Just proof -> return proof+    Nothing    -> typeMismatch Nothing (Left "HBool") (Right typ)++jmEq1_ :: Sing (a :: Hakaru)+       -> Sing (b :: Hakaru)+       -> TypeCheckMonad (TypeEq a b)+jmEq1_ typA typB =+    case jmEq1 typA typB of+    Just proof -> return proof+    Nothing    -> typeMismatch Nothing (Right typA) (Right typB)+++getHEq :: Sing a -> TypeCheckMonad (HEq a)+getHEq typ =+    case hEq_Sing typ of+    Just theEq -> return theEq+    Nothing    -> missingInstance "HEq" typ Nothing++getHOrd :: Sing a -> TypeCheckMonad (HOrd a)+getHOrd typ =+    case hOrd_Sing typ of+    Just theOrd -> return theOrd+    Nothing     -> missingInstance "HOrd" typ Nothing++getHSemiring :: Sing a -> TypeCheckMonad (HSemiring a)+getHSemiring typ =+    case hSemiring_Sing typ of+    Just theSemi -> return theSemi+    Nothing      -> missingInstance "HSemiring" typ Nothing++getHRing :: Sing a -> TypeCheckMode -> TypeCheckMonad (SomeRing a)+getHRing typ mode =+    case mode of+    StrictMode -> case hRing_Sing typ of+                    Just theRing -> return (SomeRing theRing CNil)+                    Nothing      -> missingInstance "HRing" typ Nothing+    LaxMode    -> case findRing typ of+                    Just proof   -> return proof+                    Nothing      -> missingInstance "HRing" typ Nothing+    UnsafeMode -> case findRing typ of+                    Just proof   -> return proof+                    Nothing      -> missingInstance "HRing" typ Nothing++getHFractional :: Sing a -> TypeCheckMode -> TypeCheckMonad (SomeFractional a)+getHFractional typ mode =+    case mode of+    StrictMode -> case hFractional_Sing typ of+                    Just theFrac -> return (SomeFractional theFrac CNil)+                    Nothing      -> missingInstance "HFractional" typ Nothing+    LaxMode    -> case findFractional typ of+                    Just proof   -> return proof+                    Nothing      -> missingInstance "HFractional" typ Nothing+    UnsafeMode -> case findFractional typ of+                    Just proof   -> return proof+                    Nothing      -> missingInstance "HFractional" typ Nothing++++----------------------------------------------------------------+data TypedASTs (abt :: [Hakaru] -> Hakaru -> *)+    = forall b. TypedASTs !(Sing b) [abt '[] b]++{-+instance Show2 abt => Show (TypedASTs abt) where+    showsPrec p (TypedASTs typ es) =+        showParen_1x p "TypedASTs" typ es+-}+++-- TODO: can we make this lazier in the second component of 'TypedASTs'+-- so that we can perform case analysis on the type component before+-- actually evaluating 'checkOthers'? Problem is, even though we+-- have the type to return we don't know whether the whole thing+-- will succeed or not until after calling 'checkOthers'... We could+-- handle this by changing the return type to @TypeCheckMonad (exists+-- b. (Sing b, TypeCheckMonad [abt '[] b]))@ thereby making the+-- staging explicit.+--+-- | Given a list of terms which must all have the same type, try+-- inferring each term in order until one of them succeeds and then+-- check all the others against that type. This is appropriate for+-- 'StrictMode' where we won't need to insert coercions; for+-- 'LaxMode', see 'inferLubType' instead.+inferOneCheckOthers+    :: forall abt+    .  (ABT Term abt)+    => [U.AST]+    -> TypeCheckMonad (TypedASTs abt)+inferOneCheckOthers = inferOne []+    where+    inferOne :: [U.AST] -> [U.AST] -> TypeCheckMonad (TypedASTs abt)+    inferOne ls []+        | null ls   = ambiguousEmptyNary Nothing+        | otherwise = ambiguousMustCheckNary Nothing+    inferOne ls (e:rs) = do+        m <- try $ inferType e+        case m of+            Nothing                -> inferOne (e:ls) rs+            Just (TypedAST typ e') -> do+                ls' <- checkOthers typ ls+                rs' <- checkOthers typ rs+                return (TypedASTs typ (reverse ls' ++ e' : rs'))++    checkOthers+        :: forall a. Sing a -> [U.AST] -> TypeCheckMonad [abt '[] a]+    checkOthers typ = T.traverse (checkType typ)+++-- TODO: some day we may want a variant of this function which+-- returns the error message in the event that the computation fails+-- (e.g., to provide all of them if 'inferOneCheckOthers' ultimately+-- fails.+--+-- | a la @optional :: Alternative f => f a -> f (Maybe a)@ but+-- without needing the 'empty' of the 'Alternative' class.+try :: TypeCheckMonad a -> TypeCheckMonad (Maybe a)+try m = TCM $ \ctx input mode -> Right $+    case unTCM m ctx input mode of+    Left  _ -> Nothing -- Don't worry; no side effects to unwind+    Right e -> Just e++-- | Tries to typecheck in a given mode+tryWith :: TypeCheckMode -> TypeCheckMonad a -> TypeCheckMonad (Maybe a)+tryWith mode m = TCM $ \ctx input _ -> Right $+    case unTCM m ctx input mode of+    Left  _ -> Nothing+    Right e -> Just e++-- | Given a list of terms which must all have the same type, infer+-- all the terms in order and coerce them to the lub of all their+-- types. This is appropriate for 'LaxMode' where we need to insert+-- coercions; for 'StrictMode', see 'inferOneCheckOthers' instead.+inferLubType+    :: forall abt+    .  (ABT Term abt)+    => Maybe U.SourceSpan+    -> [U.AST]+    -> TypeCheckMonad (TypedASTs abt)+inferLubType s = start+    where+    start :: [U.AST] -> TypeCheckMonad (TypedASTs abt)+    start []     = ambiguousEmptyNary Nothing+    start (u:us) = do+        TypedAST  typ1 e1 <- inferType u+        TypedASTs typ2 es <- F.foldlM step (TypedASTs typ1 [e1]) us+        return (TypedASTs typ2 (reverse es))++    -- TODO: inline 'F.foldlM' and then inline this, to unpack the first argument.+    step :: TypedASTs abt -> U.AST -> TypeCheckMonad (TypedASTs abt)+    step (TypedASTs typ1 es) u = do+        TypedAST typ2 e2 <- inferType u+        case findLub typ1 typ2 of+            Nothing              -> missingLub typ1 typ2 s+            Just (Lub typ c1 c2) ->+                let es' = map (unLC_ . coerceTo c1 . LC_) es+                    e2' = unLC_ . coerceTo c2 $ LC_ e2+                in return (TypedASTs typ (e2' : es'))+++inferCaseStrict+    :: forall abt a+    .  (ABT Term abt)+    => Sing a+    -> abt '[] a+    -> [U.Branch]+    -> TypeCheckMonad (TypedAST abt)+inferCaseStrict typA e1 = inferOne []+    where+    inferOne :: [U.Branch] -> [U.Branch] -> TypeCheckMonad (TypedAST abt)+    inferOne ls []+        | null ls   = ambiguousEmptyNary Nothing+        | otherwise = ambiguousMustCheckNary Nothing+    inferOne ls (b@(U.Branch_ pat e):rs) = do+        SP pat' vars <- checkPattern typA pat+        m <- try $ inferBinders vars e $ \typ e' -> do+                    ls' <- checkOthers typ ls+                    rs' <- checkOthers typ rs+                    return (TypedAST typ $ syn (Case_ e1 (reverse ls' ++ (Branch pat' e') : rs')))+        case m of+            Nothing -> inferOne (b:ls) rs+            Just m' -> return m'++    checkOthers+        :: forall b. Sing b -> [U.Branch] -> TypeCheckMonad [Branch a abt b]+    checkOthers typ = T.traverse (checkBranch typA typ)++data SomeBranch a abt = forall b. SomeBranch !(Sing b) [Branch a abt b]++-- TODO: find a better name, and move to where 'LC_' is defined.+lc :: (LC_ abt a -> LC_ abt b) -> abt '[] a -> abt '[] b+lc f = unLC_ . f . LC_++coerceTo_nonLC :: (ABT Term abt) => Coercion a b -> abt xs a -> abt xs b+coerceTo_nonLC = underBinders . lc . coerceTo++coerceFrom_nonLC :: (ABT Term abt) => Coercion a b -> abt xs b -> abt xs a+coerceFrom_nonLC = underBinders . lc . coerceFrom++-- BUG: how to make this not an orphan, without dealing with cyclic imports between AST.hs (for the 'LC_' instance), Datum.hs, and Coercion.hs?+instance (ABT Term abt) => Coerce (Branch a abt) where+    coerceTo   c (Branch pat e) = Branch pat (coerceTo_nonLC   c e)+    coerceFrom c (Branch pat e) = Branch pat (coerceFrom_nonLC c e)+++inferCaseLax+    :: forall abt a+    .  (ABT Term abt)+    => Maybe U.SourceSpan+    -> Sing a+    -> abt '[] a+    -> [U.Branch]+    -> TypeCheckMonad (TypedAST abt)+inferCaseLax s typA e1 = start+    where+    start :: [U.Branch] -> TypeCheckMonad (TypedAST abt)+    start []     = ambiguousEmptyNary Nothing+    start ((U.Branch_ pat e):us) = do+        SP pat' vars <- checkPattern typA pat+        inferBinders vars e $ \typ1 e' -> do+            SomeBranch typ2 bs <- F.foldlM step (SomeBranch typ1 [Branch pat' e']) us+            return . TypedAST typ2 . syn . Case_ e1 $ reverse bs++    -- TODO: inline 'F.foldlM' and then inline this, to unpack the first argument.+    step :: SomeBranch a abt+        -> U.Branch+        -> TypeCheckMonad (SomeBranch a abt)+    step (SomeBranch typB bs) (U.Branch_ pat e) = do+        SP pat' vars <- checkPattern typA pat+        inferBinders vars e $ \typE e' ->+            case findLub typB typE of+            Nothing                     -> missingLub typB typE s+            Just (Lub typLub coeB coeE) ->+                return $ SomeBranch typLub+                    ( Branch pat' (coerceTo_nonLC coeE e')+                    : map (coerceTo coeB) bs+                    )++----------------------------------------------------------------+----------------------------------------------------------------++-- HACK: we must add the constraints that 'LCs' and 'UnLCs' are inverses.+-- TODO: how can we do that in general rather than needing to repeat+-- it here and in the various constructors of 'SCon'?+checkSArgs+    :: (ABT Term abt, typs ~ UnLCs args, args ~ LCs typs)+    => List1 Sing typs+    -> [U.AST]+    -> TypeCheckMonad (SArgs abt args)+checkSArgs Nil1             []     = return End+checkSArgs (Cons1 typ typs) (e:es) =+    (:*) <$> checkType typ e <*> checkSArgs typs es+checkSArgs _ _ =+    error "checkSArgs: the number of types and terms doesn't match up"+++-- | Given a typing environment, a type, and a term, verify that+-- the term satisfies the type (and produce an elaborated term):+--+-- > Γ ⊢ τ ∋ e ⇒ e'+checkType+    :: forall abt a+    .  (ABT Term abt)+    => Sing a+    -> U.AST+    -> TypeCheckMonad (abt '[] a)+checkType = checkType_+    where+    -- HACK: to convince GHC to stop being stupid about resolving+    -- the \"choice\" of @abt'@. I'm not sure why we don't need to+    -- use this same hack when 'inferType' calls 'checkType', but whatevs.+    inferType_ :: U.AST -> TypeCheckMonad (TypedAST abt)+    inferType_ = inferType++    checkVariable+        :: forall b+        .  Sing b+        -> Maybe U.SourceSpan+        -> Variable 'U.U+        -> TypeCheckMonad (abt '[] b)+    checkVariable typ0 sourceSpan x = do+      TypedAST typ' e0' <- inferType_ (var x)+      mode <- getMode+      case mode of+        StrictMode ->+            case jmEq1 typ0 typ' of+              Just Refl -> return e0'+              Nothing   -> typeMismatch sourceSpan (Right typ0) (Right typ')+        LaxMode    -> checkOrCoerce       sourceSpan e0' typ' typ0+        UnsafeMode -> checkOrUnsafeCoerce sourceSpan e0' typ' typ0+++    checkType_+        :: forall b. Sing b -> U.AST -> TypeCheckMonad (abt '[] b)+    checkType_ typ0 e0 =+      let s = getMetadata e0 in+      caseVarSyn e0 (checkVariable typ0 s) (go s)+      where+      go sourceSpan t =+        case t of+        -- Change of direction rule suggests this doesn't need to be here+        -- We keep it here in case, we later use a U.Lam which doesn't+        -- carry the type of its variable +        U.Lam_ (U.SSing typ) e1 ->+            case typ0 of+            SFun typ1 typ2 ->+                case jmEq1 typ1 typ of+                  Just Refl -> do e1' <- checkBinder typ1 typ2 e1+                                  return $ syn (Lam_ :$ e1' :* End)+                  Nothing   -> typeMismatch sourceSpan (Right typ1) (Right typ)+            _ -> typeMismatch sourceSpan (Right typ0) (Left "function type")++        U.Let_ e1 e2 -> do+            TypedAST typ1 e1' <- inferType_ e1+            e2' <- checkBinder typ1 typ0 e2+            return $ syn (Let_ :$ e1' :* e2' :* End)++        U.CoerceTo_ (Some2 c) e1 ->+            case singCoerceDomCod c of+            Nothing -> do+                e1' <- checkType_ typ0 e1+                return $ syn (CoerceTo_ CNil :$  e1' :* End)+            Just (dom, cod) ->+                case jmEq1 typ0 cod of+                Just Refl -> do+                    e1' <- checkType_ dom e1+                    return $ syn (CoerceTo_ c :$ e1' :* End)+                Nothing -> typeMismatch sourceSpan (Right typ0) (Right cod)++        U.UnsafeTo_ (Some2 c) e1 ->+            case singCoerceDomCod c of+            Nothing -> do+                e1' <- checkType_ typ0 e1+                return $ syn (UnsafeFrom_ CNil :$  e1' :* End)+            Just (dom, cod) ->+                case jmEq1 typ0 dom of+                Just Refl -> do+                    e1' <- checkType_ cod e1+                    return $ syn (UnsafeFrom_ c :$ e1' :* End)+                Nothing -> typeMismatch sourceSpan (Right typ0) (Right dom)++        -- TODO: Find better place to put this logic+        U.PrimOp_ U.Infinity [] -> do+            case typ0 of+              SNat  -> return $+                         syn (PrimOp_ (Infinity HIntegrable_Nat) :$ End)+              SInt  -> checkOrCoerce sourceSpan (syn (PrimOp_ (Infinity HIntegrable_Nat) :$ End))+                         SNat+                         SInt+              SProb -> return $+                         syn (PrimOp_ (Infinity HIntegrable_Prob) :$ End)+              SReal -> checkOrCoerce sourceSpan (syn (PrimOp_ (Infinity HIntegrable_Prob) :$ End))+                         SProb+                         SReal+              _     -> failwith =<<+                        makeErrMsg+                         "Type Mismatch:"+                         sourceSpan+                         "infinity can only be checked against nat or prob"++        U.NaryOp_ op es -> do+            mode <- getMode+            case mode of+              StrictMode -> safeNaryOp typ0+              LaxMode    -> safeNaryOp typ0+              UnsafeMode -> do+                es' <- tryWith LaxMode (safeNaryOp typ0)+                case es' of+                  Just es'' -> return es''+                  Nothing   -> do+                    TypedAST typ e0' <- inferType (syn $ U.NaryOp_ op es)+                    checkOrUnsafeCoerce sourceSpan e0' typ typ0+            where+            safeNaryOp :: forall c. Sing c -> TypeCheckMonad (abt '[] c)+            safeNaryOp typ = do+                op'  <- make_NaryOp typ op+                es'  <- T.forM es $ checkType_ typ+                return $ syn (NaryOp_ op' (S.fromList es'))++        U.Empty_ ->+            case typ0 of+            SArray _ -> return $ syn (Empty_ typ0)+            _        -> typeMismatch sourceSpan (Right typ0) (Left "HArray")++        U.Pair_ e1 e2 ->+            case typ0 of+            SData (STyCon sym `STyApp` a `STyApp` b) _ ->+                case jmEq1 sym sSymbol_Pair of+                Just Refl  -> do+                    e1' <- checkType_ a e1+                    e2' <- checkType_ b e2+                    return $ syn (Datum_ $ dPair_ a b e1' e2')+                Nothing    -> typeMismatch sourceSpan (Right typ0) (Left "HPair")+            _              -> typeMismatch sourceSpan (Right typ0) (Left "HPair")++        U.Array_ e1 e2 ->+            case typ0 of+            SArray typ1 -> do+                e1' <- checkType_  SNat e1+                e2' <- checkBinder SNat typ1 e2+                return $ syn (Array_ e1' e2')+            _ -> typeMismatch sourceSpan (Right typ0) (Left "HArray")++        U.Datum_ (U.Datum hint d) ->+            case typ0 of+            SData _ typ2 ->+                (syn . Datum_ . Datum hint typ0)+                    <$> checkDatumCode typ0 typ2 d+            _ -> typeMismatch sourceSpan (Right typ0) (Left "HData")++        U.Case_ e1 branches -> do+            TypedAST typ1 e1' <- inferType_ e1+            branches' <- T.forM branches $ checkBranch typ1 typ0+            return $ syn (Case_ e1' branches')++        U.Dirac_ e1 ->+            case typ0 of+            SMeasure typ1 -> do+                e1' <- checkType_ typ1 e1+                return $ syn (Dirac :$ e1' :* End)+            _ -> typeMismatch sourceSpan (Right typ0) (Left "HMeasure")++        U.MBind_ e1 e2 ->+            case typ0 of+            SMeasure _ -> do+                TypedAST typ1 e1' <- inferType_ e1+                case typ1 of+                    SMeasure typ2 -> do+                        e2' <- checkBinder typ2 typ0 e2+                        return $ syn (MBind :$ e1' :* e2' :* End)+                    _ -> typeMismatch sourceSpan (Right typ0) (Right typ1)+            _ -> typeMismatch sourceSpan (Right typ0) (Left "HMeasure")++        U.Plate_ e1 e2 ->+            case typ0 of+            SMeasure typ1 -> do+                e1' <- checkType_ SNat e1+                case typ1 of+                    SArray typ2 -> do+                        e2' <- checkBinder SNat (SMeasure typ2) e2+                        return $ syn (Plate :$ e1' :* e2' :* End)+                    _ -> typeMismatch sourceSpan (Right typ1) (Left "HArray")+            _ -> typeMismatch sourceSpan (Right typ0) (Left "HMeasure")++        U.Chain_ e1 e2 e3 ->+            case typ0 of+            SMeasure (SData (STyCon sym `STyApp` (SArray a) `STyApp` s) _) ->+                case jmEq1 sym sSymbol_Pair of+                Just Refl -> do+                    e1' <- checkType_  SNat e1+                    e2' <- checkType_  s    e2+                    e3' <- checkBinder s    (SMeasure $ sPair a s) e3+                    return $ syn (Chain :$ e1' :* e2' :* e3' :* End)+                Nothing -> typeMismatch sourceSpan (Right typ0) (Left "HMeasure(HPair(HArray, s)")+            _           -> typeMismatch sourceSpan (Right typ0) (Left "HMeasure(HPair(HArray, s)")+++        U.Expect_ e1 e2 ->+            case typ0 of+            SProb -> do+                TypedAST typ1 e1' <- inferType_ e1+                case typ1 of+                    SMeasure typ2 -> do+                        e2' <- checkBinder typ2 typ0 e2+                        return $ syn (Expect :$ e1' :* e2' :* End)+                    _ -> typeMismatch sourceSpan (Left "HMeasure") (Right typ1)+            _ -> typeMismatch sourceSpan (Right typ0) (Left "HProb")++        U.Observe_ e1 e2 ->+            case typ0 of+            SMeasure typ2 -> do+                e1' <- checkType_ typ0 e1+                e2' <- checkType_ typ2 e2+                return $ syn (Observe :$ e1' :* e2' :* End)+            _ -> typeMismatch sourceSpan (Right typ0) (Left "HMeasure")++        U.Superpose_ pes ->+            case typ0 of+            SMeasure _ ->+                fmap (syn . Superpose_) .+                    T.forM pes $ \(p,e) ->+                        (,) <$> checkType_ SProb p <*> checkType_ typ0 e+            _ -> typeMismatch sourceSpan (Right typ0) (Left "HMeasure")++        U.Reject_ ->+            case typ0 of+            SMeasure _ -> return $ syn (Reject_ typ0)+            _          -> typeMismatch sourceSpan (Right typ0) (Left "HMeasure")++        _   | inferable e0 -> do+                TypedAST typ' e0' <- inferType_ e0+                mode <- getMode+                case mode of+                  StrictMode ->+                    case jmEq1 typ0 typ' of+                    Just Refl -> return e0'+                    Nothing   -> typeMismatch sourceSpan (Right typ0) (Right typ')+                  LaxMode    -> checkOrCoerce       sourceSpan e0' typ' typ0+                  UnsafeMode -> checkOrUnsafeCoerce sourceSpan e0' typ' typ0+            | otherwise -> error "checkType: missing an mustCheck branch!"+++    --------------------------------------------------------+    -- We make these local to 'checkType' for the same reason we have 'checkType_'+    -- TODO: can we combine these in with the 'checkBranch' functions somehow?+    checkDatumCode+        :: forall xss t+        .  Sing (HData' t)+        -> Sing xss+        -> U.DCode_+        -> TypeCheckMonad (DatumCode xss (abt '[]) (HData' t))+    checkDatumCode typA typ d =+        case d of+        U.Inr d2 ->+            case typ of+            SPlus _ typ2 -> Inr <$> checkDatumCode typA typ2 d2+            _            -> failwith_ "expected datum of `inr' type"+        U.Inl d1 ->+            case typ of+            SPlus typ1 _ -> Inl <$> checkDatumStruct typA typ1 d1+            _            -> failwith_ "expected datum of `inl' type"++    checkDatumStruct+        :: forall xs t+        .  Sing (HData' t)+        -> Sing xs+        -> U.DStruct_+        -> TypeCheckMonad (DatumStruct xs (abt '[]) (HData' t))+    checkDatumStruct typA typ d =+        case d of+        U.Et d1 d2 ->+            case typ of+            SEt typ1 typ2 -> Et+                <$> checkDatumFun    typA typ1 d1+                <*> checkDatumStruct typA typ2 d2+            _     -> failwith_ "expected datum of `et' type"+        U.Done ->+            case typ of+            SDone -> return Done+            _     -> failwith_ "expected datum of `done' type"++    checkDatumFun+        :: forall x t+        .  Sing (HData' t)+        -> Sing x+        -> U.DFun_+        -> TypeCheckMonad (DatumFun x (abt '[]) (HData' t))+    checkDatumFun typA typ d =+        case d of+        U.Ident e1 ->+            case typ of+            SIdent      -> Ident <$> checkType_ typA e1+            _           -> failwith_ "expected datum of `I' type"+        U.Konst e1 ->+            case typ of+            SKonst typ1 -> Konst <$> checkType_ typ1 e1+            _           -> failwith_ "expected datum of `K' type"+++----------------------------------------------------------------+-- BUG: haddock doesn't like annotations on GADT constructors. So+-- here we'll avoid using the GADT syntax, even though it'd make+-- the data type declaration prettier\/cleaner.+-- <https://github.com/hakaru-dev/hakaru/issues/6>+data SomePattern (a :: Hakaru) =+    forall vars.+        SP  !(Pattern vars a)+            !(List1 Variable vars)++data SomePatternCode xss t =+    forall vars.+        SPC !(PDatumCode xss vars (HData' t))+            !(List1 Variable vars)++data SomePatternStruct xs t =+    forall vars.+        SPS !(PDatumStruct xs vars (HData' t))+            !(List1 Variable vars)++data SomePatternFun x t =+    forall vars.+        SPF !(PDatumFun x vars (HData' t))+            !(List1 Variable vars)++checkBranch+    :: (ABT Term abt)+    => Sing a+    -> Sing b+    -> U.Branch+    -> TypeCheckMonad (Branch a abt b)+checkBranch patTyp bodyTyp (U.Branch_ pat body) = do+    SP pat' vars <- checkPattern patTyp pat+    Branch pat' <$> checkBinders vars bodyTyp body++checkPattern+    :: Sing a+    -> U.Pattern+    -> TypeCheckMonad (SomePattern a)+checkPattern = \typA pat ->+    case pat of+    U.PVar x -> return $ SP PVar (Cons1 (makeVar (U.nameToVar x) typA) Nil1)+    U.PWild  -> return $ SP PWild Nil1+    U.PDatum hint pat1 ->+        case typA of+        SData _ typ1 -> do+            SPC pat1' xs <- checkPatternCode typA typ1 pat1+            return $ SP (PDatum hint pat1') xs+        _ -> typeMismatch Nothing (Right typA) (Left "HData")+    where+    checkPatternCode+        :: Sing (HData' t)+        -> Sing xss+        -> U.PCode+        -> TypeCheckMonad (SomePatternCode xss t)+    checkPatternCode typA typ pat =+        case pat of+        U.PInr pat2 ->+            case typ of+            SPlus _ typ2 -> do+                SPC pat2' xs <- checkPatternCode typA typ2 pat2+                return $ SPC (PInr pat2') xs+            _            -> failwith_ "expected pattern of `sum' type"+        U.PInl pat1 ->+            case typ of+            SPlus typ1 _ -> do+                SPS pat1' xs <- checkPatternStruct typA typ1 pat1+                return $ SPC (PInl pat1') xs+            _ -> failwith_ "expected pattern of `zero' type"++    checkPatternStruct+        :: Sing (HData' t)+        -> Sing xs+        -> U.PStruct+        -> TypeCheckMonad (SomePatternStruct xs t)+    checkPatternStruct  typA typ pat =+        case pat of+        U.PEt pat1 pat2 ->+            case typ of+            SEt typ1 typ2 -> do+                SPF pat1' xs <- checkPatternFun    typA typ1 pat1+                SPS pat2' ys <- checkPatternStruct typA typ2 pat2+                return $ SPS (PEt pat1' pat2') (append1 xs ys)+            _ -> failwith_ "expected pattern of `et' type"+        U.PDone ->+            case typ of+            SDone -> return $ SPS PDone Nil1+            _     -> failwith_ "expected pattern of `done' type"++    checkPatternFun+        :: Sing (HData' t)+        -> Sing x+        -> U.PFun+        -> TypeCheckMonad (SomePatternFun x t)+    checkPatternFun typA typ pat =+        case pat of+        U.PIdent pat1 ->+            case typ of+            SIdent -> do+                SP pat1' xs <- checkPattern typA pat1+                return $ SPF (PIdent pat1') xs+            _ -> failwith_ "expected pattern of `I' type"+        U.PKonst pat1 ->+            case typ of+            SKonst typ1 -> do+                SP pat1' xs <- checkPattern typ1 pat1+                return $ SPF (PKonst pat1') xs+            _ -> failwith_ "expected pattern of `K' type"++checkOrCoerce+    :: (ABT Term abt)+    => Maybe (U.SourceSpan)+    -> abt '[] a+    -> Sing a+    -> Sing b+    -> TypeCheckMonad (abt '[] b)+checkOrCoerce s e typA typB =+    case findCoercion typA typB of+    Just c  -> return . unLC_ . coerceTo c $ LC_ e+    Nothing -> typeMismatch s (Right typB) (Right typA)++checkOrUnsafeCoerce+    :: (ABT Term abt)+    => Maybe (U.SourceSpan)+    -> abt '[] a+    -> Sing a+    -> Sing b+    -> TypeCheckMonad (abt '[] b)+checkOrUnsafeCoerce s e typA typB =+    case findEitherCoercion typA typB of+    Just (Unsafe  c) ->+        return . unLC_ . coerceFrom c $ LC_ e+    Just (Safe    c) ->+        return . unLC_ . coerceTo c $ LC_ e+    Just (Mixed   (_, c1, c2)) ->+        return . unLC_ . coerceTo c2 . coerceFrom c1 $ LC_ e+    Nothing ->+        case (typA, typB) of+          -- mighty, mighty hack!+          (SMeasure typ1, SMeasure _) -> do+            let x = Variable (pack "") 0 U.SU+            e2' <- checkBinder typ1 typB (bind x $ syn $ U.Dirac_ (var x))+            return $ syn (MBind :$ e :* e2' :* End)+          (_ ,  _) -> typeMismatch s (Right typB) (Right typA)++++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Syntax/TypeOf.hs view
@@ -0,0 +1,195 @@+{-# LANGUAGE CPP+           , DataKinds+           , KindSignatures+           , GADTs+           , ScopedTypeVariables+           , Rank2Types+           , FlexibleContexts+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.02.23+-- |+-- Module      :  Language.Hakaru.Syntax.TypeOf+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- BUG: can't put this in "Language.Hakaru.Syntax.AST.Sing" because+-- of some sort of cyclic dependency...+----------------------------------------------------------------+module Language.Hakaru.Syntax.TypeOf+    (+    -- * Get singletons for well-typed ABTs+      typeOf+    +    -- * Implementation details+    , getTermSing+    ) where++import qualified Data.Foldable as F+#if __GLASGOW_HASKELL__ < 710+import Data.Functor ((<$>))+#endif++import Language.Hakaru.Syntax.IClasses (Pair2(..), fst2, snd2)+import Language.Hakaru.Syntax.Variable (varType)+import Language.Hakaru.Syntax.ABT      (ABT, caseBind, paraABT)+import Language.Hakaru.Types.DataKind  (Hakaru())+import Language.Hakaru.Types.HClasses  (sing_HSemiring)+import Language.Hakaru.Types.Sing      (Sing(..), sUnMeasure)+import Language.Hakaru.Types.Coercion+    (singCoerceCod, singCoerceDom, Coerce(..))+import Language.Hakaru.Syntax.Datum    (Datum(..), Branch(..))+import Language.Hakaru.Syntax.AST      (Term(..), SCon(..), SArgs(..))+import Language.Hakaru.Syntax.AST.Sing+    (sing_PrimOp, sing_ArrayOp, sing_MeasureOp, sing_NaryOp, sing_Literal)++----------------------------------------------------------------+----------------------------------------------------------------++-- | Given any well-typed term, produce its type.+--+-- TODO: at present this function may throw errors; in particular,+-- whenever encountering a 'Case_' or 'Superpose_' which is either+-- empty or where all the branches fail. This is considered a bug+-- (since all well-typed terms should be able to produce their+-- types), however it only arises on programs which are (at least+-- partially) undefined or (where defined) are the zero measure,+-- so fixing this is a low priority. When working to correct this+-- bug, it is strongly discouraged to try correcting it by adding+-- singletons to the 'Case_' and 'Superpose_' constructors; since+-- doing so will cause a lot of code to break (and therefore is not+-- a lightweight change), as well as greatly increasing the memory+-- cost for storing ASTs. It would be much better to consider whole+-- programs as being something more than just the AST, thus when+-- trying to get the type of subterms (which should be the only+-- time we ever call this function) we should have access to some+-- sort of context, or intern-table for type singletons, or whatever+-- else makes something a whole program.+--+-- N.B., this is a bit of a hack in order to avoid using 'SingI'+-- or needing to memoize the types of everything. You should really+-- avoid using this function if at all possible since it's very+-- expensive.+typeOf :: (ABT Term abt) => abt '[] a -> Sing a+typeOf e0 =+    case typeOf_ e0 of+    Left  err -> error $ "typeOf: " ++ err+    Right typ -> typ+++-- | For private use only.+typeOf_ :: (ABT Term abt) => abt '[] a -> Either String (Sing a)+typeOf_+    = unLiftSing+    . paraABT+        (LiftSing . return . varType)+        (\_ _ -> LiftSing . unLiftSing) -- cast out phantoms+        (LiftSing . getTermSing unLiftSing)+++-- | This newtype serves two roles. First we add the phantom @xs@+-- so that we can fit this in with the types of 'paraABT'. And+-- second, we wrap up the 'Sing' in a monad for capturing errors,+-- so that we can bring them all the way to the top of the term+-- before deciding whether to throw them or not.+newtype LiftSing (xs :: [Hakaru]) (a :: Hakaru) =+    LiftSing { unLiftSing :: Either String (Sing a) }+++----------------------------------------------------------------+-- | This is the core of the 'Term'-algebra for computing 'typeOf'.+-- It is exported because it is useful for constructing other+-- 'Term'-algebras for use with 'paraABT'; namely, for callers who+-- need singletons for every subterm while converting an ABT to+-- something else (e.g., pretty printing).+--+-- The @r@ type is whatever it is you're building up via 'paraABT'.+-- The first argument to 'getTermSing' gives some way of projecting+-- a singleton out of @r@ (to avoid the need to map that projection+-- over the term before calling 'getTermSing'). You can then use+-- the resulting singleton for constructing the overall @r@ to be+-- returned.+--+-- If this function returns 'Left', this is considered an error+-- (see the description of 'typeOf'). We pose things in this form+-- (rather than throwing the error immediately) because it enables+-- us to automatically recover from certain error situations.+getTermSing+    :: forall abt r+    .  (ABT Term abt)+    => (forall xs a. r xs a -> Either String (Sing a))+    -> forall a+    .  Term (Pair2 abt r) a+    -> Either String (Sing a)+getTermSing singify = go+    where+    getSing :: forall xs a. Pair2 abt r xs a -> Either String (Sing a)+    getSing = singify . snd2+    {-# INLINE getSing #-}++    getBranchSing+        :: forall a b+        .  Branch a (Pair2 abt r) b+        -> Either String (Sing b)+    getBranchSing (Branch _ e) = getSing e+    {-# INLINE getBranchSing #-}++    go :: forall a. Term (Pair2 abt r) a -> Either String (Sing a)+    go (Lam_ :$ r1 :* End) =+        caseBind (fst2 r1) $ \x _ ->+            SFun (varType x) <$> getSing r1+    go (App_ :$ r1 :* _ :* End) = do+        typ1 <- getSing r1+        case typ1 of+            SFun _ typ3            -> return typ3+            _ -> error "getTermSing: the impossible happened"+    go (Let_ :$ _  :* r2 :* End)    = getSing r2+    go (CoerceTo_   c :$ r1 :* End) =+        maybe (coerceTo   c <$> getSing r1) return (singCoerceCod c)+    go (UnsafeFrom_ c :$ r1 :* End) =+        maybe (coerceFrom c <$> getSing r1) return (singCoerceDom c)+    go (PrimOp_     o :$ _)         = return . snd $ sing_PrimOp o+    go (ArrayOp_    o :$ _)         = return . snd $ sing_ArrayOp o+    go (MeasureOp_  o :$ _)         =+        return . SMeasure . snd $ sing_MeasureOp o+    go (Dirac  :$ r1 :* End)        = SMeasure <$> getSing r1+    go (MBind  :$ _  :* r2 :* End)  = getSing r2+    go (Plate  :$ _  :* r2 :* End)  = SMeasure . SArray . sUnMeasure <$> getSing r2+    go (Integrate :$  _)            = return SProb+    go (Summate _ h :$  _)          = return $ sing_HSemiring h+    go (Product _ h :$  _)          = return $ sing_HSemiring h+    go (Expect :$  _)               = return SProb+    go (Observe :$ r1 :* _ :* End)  = getSing r1+    go (NaryOp_  o  _)              = return $ sing_NaryOp o+    go (Literal_ v)                 = return $ sing_Literal v+    go (Empty_   typ)               = return typ+    go (Array_   _  r2)             = SArray <$> getSing r2+    go (Datum_ (Datum _ typ _))     = return typ+    go (Case_    _  bs) = tryAll "Case_"      getBranchSing   bs+    go (Superpose_ pes) = tryAll "Superpose_" (getSing . snd) pes+    go (Reject_ typ)    = return typ+    go (_ :$ _) = error "getTermSing: the impossible happened"+++tryAll+    :: F.Foldable f+    => String+    -> (a -> Either String b)+    -> f a+    -> Either String b+tryAll name f =+    F.foldr step (Left $ "no unique type for " ++ name)+    where+    step x rest =+        case f x of+        r@(Right _) -> r+        Left _      -> rest+{-# INLINE tryAll #-}++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Syntax/Value.hs view
@@ -0,0 +1,106 @@+{-# LANGUAGE CPP+           , DataKinds+           , PolyKinds+           , GADTs+           , TypeOperators+           , EmptyCase+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+module Language.Hakaru.Syntax.Value where++import           Language.Hakaru.Syntax.IClasses+import           Language.Hakaru.Syntax.Datum+import           Language.Hakaru.Types.HClasses+import           Language.Hakaru.Types.DataKind+import           Language.Hakaru.Types.Coercion++import qualified Data.Vector                     as V+import qualified Data.Number.LogFloat            as LF+import           Data.Number.Nat++import qualified System.Random.MWC               as MWC++data Value :: Hakaru -> * where+     VNat     :: {-# UNPACK #-} !Nat -> Value 'HNat+     VInt     :: {-# UNPACK #-} !Int -> Value 'HInt+     VProb    :: {-# UNPACK #-} !LF.LogFloat -> Value 'HProb+     VReal    :: {-# UNPACK #-} !Double -> Value 'HReal++     VDatum   :: !(Datum Value (HData' t)) -> Value (HData' t)++     -- Assuming you want to consider lambdas/closures to be values.+     -- N.B., the type below is larger than is correct; that is,+     VLam     :: (Value a -> Value b) -> Value (a ':-> b)++     -- Measures hold their importance weight and random seed+     VMeasure :: (Value 'HProb ->+                  MWC.GenIO    ->+                  IO (Maybe (Value a, Value 'HProb))+                 ) -> Value ('HMeasure a)+     VArray   :: {-# UNPACK #-} !(V.Vector (Value a)) -> Value ('HArray a)++instance Eq1 Value where+    eq1 (VNat  a) (VNat  b) = a == b+    eq1 (VInt  a) (VInt  b) = a == b+    eq1 (VProb a) (VProb b) = a == b+    eq1 (VReal a) (VReal b) = a == b+    eq1 _        _        = False++instance Eq (Value a) where+    (==) = eq1++instance Show1 Value where+    showsPrec1 p (VNat   v)   = showsPrec  p v+    showsPrec1 p (VInt   v)   = showsPrec  p v+    showsPrec1 p (VProb  v)   = showsPrec  p v+    showsPrec1 p (VReal  v)   = showsPrec  p v+    showsPrec1 p (VDatum d)   = showsPrec1 p d+    showsPrec1 _ (VLam   _)   = showString "<function>"+    showsPrec1 _ (VMeasure _) = showString "<measure>"+    showsPrec1 p (VArray e)   = showsPrec  p e++instance Show (Value a) where+    showsPrec = showsPrec1+    show      = show1++instance Coerce Value where+    coerceTo   CNil         v = v+    coerceTo   (CCons c cs) v = coerceTo cs (primCoerceTo c v)++    coerceFrom CNil         v = v+    coerceFrom (CCons c cs) v = primCoerceFrom c (coerceFrom cs v)++instance PrimCoerce Value where+    primCoerceTo c l =+        case (c,l) of+        (Signed HRing_Int,            VNat  a) -> VInt  $ fromNat a+        (Signed HRing_Real,           VProb a) -> VReal $ LF.fromLogFloat a+        (Continuous HContinuous_Prob, VNat  a) ->+            VProb $ LF.logFloat (fromIntegral (fromNat a) :: Double)+        (Continuous HContinuous_Real, VInt  a) -> VReal $ fromIntegral a+        _ -> error "no a defined primitive coercion"++    primCoerceFrom c l =+        case (c,l) of+        (Signed HRing_Int,            VInt  a) -> VNat  $ unsafeNat a+        (Signed HRing_Real,           VReal a) -> VProb $ LF.logFloat a+        (Continuous HContinuous_Prob, VProb a) ->+            VNat $ unsafeNat $ floor (LF.fromLogFloat a :: Double)+        (Continuous HContinuous_Real, VReal a) -> VInt  $ floor a+        _ -> error "no a defined primitive coercion"+++lam2 :: Value (a ':-> b ':-> c) -> (Value a -> Value b -> Value c)+lam2 (VLam f1) v1 =+    case f1 v1 of+    VLam f2 -> f2+    _       -> error "lam2: the impossible happened"++enumFromUntilValue+    :: (HDiscrete a)+    -> Value a+    -> Value a+    -> [Value a]+enumFromUntilValue _ (VNat lo) (VNat hi) = map VNat (init (enumFromTo lo hi))+enumFromUntilValue _ (VInt lo) (VInt hi) = map VInt (init (enumFromTo lo hi))
+ haskell/Language/Hakaru/Syntax/Variable.hs view
@@ -0,0 +1,561 @@+{-# LANGUAGE CPP+           , GADTs+           , DataKinds+           , PolyKinds+           , FlexibleContexts+           , DeriveDataTypeable+           , ExistentialQuantification+           , UndecidableInstances+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.04.28+-- |+-- Module      :  Language.Hakaru.Syntax.Variable+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- An implementation of variables, for use with "Language.Hakaru.Syntax.ABT".+----------------------------------------------------------------+module Language.Hakaru.Syntax.Variable+    (+    -- * Our basic notion of variables.+      Variable(..)+    , varEq+    , VarEqTypeError(..)+    -- ** Variables with existentially quantified types+    , KindOf+    , SomeVariable(..)+    +    -- * Some helper types for \"heaps\", \"environments\", etc+    -- ** Typing environments; aka: sets of (typed) variables+    , VarSet(..)+    , emptyVarSet+    , singletonVarSet+    , fromVarSet+    , toVarSet+    , toVarSet1+    , insertVarSet+    , deleteVarSet+    , memberVarSet+    , nextVarID+    -- ** Substitutions; aka: maps from variables to their definitions+    , Assoc(..)+    , Assocs(..) -- TODO: hide the data constructors+    , emptyAssocs+    , singletonAssocs+    , fromAssocs+    , toAssocs+    , toAssocs1+    , insertAssoc+    , insertAssocs+    , lookupAssoc+    , adjustAssoc+    , mapAssocs+    ) where++import           Data.Proxy        (KProxy(..))+import           Data.Typeable     (Typeable)+import           Data.Text         (Text)+import           Data.IntMap       (IntMap)+import qualified Data.IntMap       as IM+import           Data.Function     (on)+import           Control.Exception (Exception, throw)+#if __GLASGOW_HASKELL__ < 710+import           Data.Monoid       (Monoid(..))+#endif++import Data.Number.Nat+import Language.Hakaru.Syntax.IClasses+-- TODO: factor the definition of the 'Sing' type family out from+-- the instances, so that we can make our ABT stuff totally independent+-- of the definition of Hakaru's types.+import Language.Hakaru.Types.Sing++----------------------------------------------------------------+----------------------------------------------------------------+-- TODO: should we make this type abstract, or type-class it?++-- TODO: alas we need to keep the Sing in order to make 'subst'+-- typesafe... Is there any way to work around that? Maybe only+-- define substitution for well-typed ABTs (i.e., what we produce+-- via typechecking a plain ABT)? If we can manage to get rid of+-- the Sing, then 'binder' and 'multibinder' would become much+-- simpler. Alas, it looks like we also need it for 'inferType' to+-- be well-typed... How can we avoid that?+--+-- TODO: what are the overhead costs of storing a Sing? Would+-- it be cheaper to store the SingI dictionary (and a Proxy,+-- as necessary)?+++-- | A variable is a triple of a unique identifier ('varID'), a+-- hint for how to display things to humans ('varHint'), and a type+-- ('varType'). Notably, the hint is only used for display purposes,+-- and the type is only used for typing purposes; thus, the 'Eq'+-- and 'Ord' instances only look at the unique identifier, completely+-- ignoring the other two components. However, the 'varEq' function+-- does take the type into consideration (but still ignores the+-- hint).+--+-- N.B., the unique identifier is lazy so that we can tie-the-knot+-- in 'binder'.+data Variable (a :: k) = Variable+    { varHint :: {-# UNPACK #-} !Text+    , varID   :: Nat -- N.B., lazy!+    , varType :: !(Sing a)+    }++-- TODO: instance Read (Variable a)++-- HACK: this requires UndecidableInstances+instance Show1 (Sing :: k -> *) => Show1 (Variable :: k -> *) where+    showsPrec1 p (Variable hint i typ) =+        showParen (p > 9)+            ( showString "Variable "+            . showsPrec  11 hint+            . showString " "+            . showsPrec  11 i+            . showString " "+            . showsPrec1 11 typ+            )++instance Show (Sing a) => Show (Variable a) where+    showsPrec p (Variable hint i typ) =+        showParen (p > 9)+            ( showString "Variable "+            . showsPrec  11 hint+            . showString " "+            . showsPrec  11 i+            . showString " "+            . showsPrec  11 typ+            )++-- BUG: these may not be consistent with the interpretation chosen by 'varEq'+instance Eq1 Variable where+    eq1 = (==) `on` varID++instance Eq (Variable a) where+    (==) = (==) `on` varID+++-- BUG: this must be consistent with the 'Eq' instance, but should+-- also be consistent with the 'varEq' interpretation. In particular,+-- it's not clear how to make any Ord instance consistent with+-- interpretation #1 (unless we have some sort of `jmCompare` on+-- types!)+instance Ord (Variable a) where+    compare = compare `on` varID+++-- TODO: so long as we don't go with interpretation #1 (because+-- that'd cause consistency issues with the 'Ord' instance) we could+-- simply use this to give a 'JmEq1' instance. Would help to minimize+-- the number of distinct concepts floating around...+--+-- | Compare to variables at possibly-different types. If the+-- variables are \"equal\", then they must in fact have the same+-- type. N.B., it is not entirely specified what this function+-- /means/ when two variables have the same 'varID' but different+-- 'varType'. However, so long as we use this function everywhere,+-- at least we'll be consistent.+--+-- Possible interpretations:+--+-- * We could /assume/ that when the 'varType's do not match the+-- variables are not equal. Upside: we can statically guarantee+-- that every variable is \"well-typed\" (by fiat). Downside: every+-- type has its own variable namespace, which is very confusing.+-- Also, the @Ord SomeVariable@ instance will be really difficult+-- to get right.+--+-- * We could /require/ that whenever two 'varID's match, their+-- 'varType's must also match. Upside: a single variable namespace.+-- Downside: if the types do not in fact match (e.g., the preprocessing+-- step for ensuring variable uniqueness is buggy), then we must+-- throw (or return) an 'VarEqTypeError' exception.+--+-- * We could /assert/ that whenever two 'varID's match, their+-- 'varType's must also match. Upsides: we get a single variable+-- namespace, and we get /O(1)/ equality checking. Downsides: if+-- the types do not in fact match, we'll probably segfault.+--+-- Whichever interpretation we choose, we must make sure that typing+-- contexts, binding environments, and so on all behave consistently.+varEq+    :: (Show1 (Sing :: k -> *), JmEq1 (Sing :: k -> *))+    => Variable (a :: k)+    -> Variable (b :: k)+    -> Maybe (TypeEq a b)+{-+-- Interpretation #1:+varEq x y =+    case jmEq1 (varType x) (varType y) of+    Just Refl | x == y -> Just Refl+    _                  -> Nothing+-}+-- Interpretation #2:+varEq x y+    | varID x == varID y =+        case jmEq1 (varType x) (varType y) of+        Just Refl -> Just Refl+        Nothing   -> throw (VarEqTypeError x y)+    | otherwise = Nothing+{-+-- Interpretation #3:+varEq x y+    | varID x == varID y = Just (unsafeCoerce Refl)+    | otherwise          = Nothing+-}+++-- TODO: is there any reason we ought to parameterize 'VarEqTypeError'+-- by the kind of the variables it closes over? Packaging up the+-- dictionaries seems fine for the 'Show' and 'Exception' instances,+-- but maybe elsewhere?+--+-- | An exception type for if we need to throw an error when two+-- variables do not have an equal 'varType'. This is mainly used+-- when 'varEq' chooses the second interpretation.+data VarEqTypeError where+    VarEqTypeError+        :: (Show1 (Sing :: k -> *), JmEq1 (Sing :: k -> *))+        => {-# UNPACK #-} !(Variable (a :: k))+        -> {-# UNPACK #-} !(Variable (b :: k))+        -> VarEqTypeError+    deriving (Typeable)++instance Show VarEqTypeError where+    showsPrec p (VarEqTypeError x y) =+        showParen (p > 9)+            ( showString "VarEqTypeError "+            . showsPrec1 11 x+            . showString " "+            . showsPrec1 11 y+            )++instance Exception VarEqTypeError+++----------------------------------------------------------------+-- TODO: switch to using 'Some1' itself? Maybe no longer a good idea, due to the need for the kind parameter...++-- | Hide an existentially quantified parameter to 'Variable'.+--+-- Because the 'Variable' type is poly-kinded, we need to be careful+-- not to erase too much type\/kind information. Thus, we parameterize+-- the 'SomeVariable' type by the /kind/ of the type we existentially+-- quantify over. This is necessary for giving 'Eq' and 'Ord'+-- instances since we can only compare variables whose types live+-- in the same kind.+--+-- N.B., the 'Ord' instance assumes that 'varEq' uses either the+-- second or third interpretation. If 'varEq' uses the first+-- interpretation then, the 'Eq' instance (which uses 'varEq') will+-- be inconsistent with the 'Ord' instance!+data SomeVariable (kproxy :: KProxy k) =+    forall (a :: k) . SomeVariable+        {-# UNPACK #-} !(Variable (a :: k))+++-- | Convenient synonym to refer to the kind of a type variable:+-- @type KindOf (a :: k) = ('KProxy :: KProxy k)@+type KindOf (a :: k) = ('KProxy :: KProxy k)+++-- This instance requires the 'JmEq1' and 'Show1' constraints because we use 'varEq'.+instance (JmEq1 (Sing :: k -> *), Show1 (Sing :: k -> *))+    => Eq (SomeVariable (kproxy :: KProxy k))+    where+    SomeVariable x == SomeVariable y =+        case varEq x y of+        Just Refl -> True+        Nothing   -> False+++-- This instance requires the 'JmEq1' and 'Show1' constraints because 'Ord' requires the 'Eq' instance, which in turn requires those constraints.+instance (JmEq1 (Sing :: k -> *), Show1 (Sing :: k -> *))+    => Ord (SomeVariable (kproxy :: KProxy k))+    where+    SomeVariable x `compare` SomeVariable y =+        varID x `compare` varID y+++-- TODO: instance Read SomeVariable+++instance Show1 (Sing :: k -> *)+    => Show (SomeVariable (kproxy :: KProxy k))+    where+    showsPrec p (SomeVariable v) =+        showParen (p > 9)+            ( showString "SomeVariable "+            . showsPrec1 11 v+            )+++----------------------------------------------------------------+-- | A set of (typed) variables.+newtype VarSet (kproxy :: KProxy k) =+    VarSet { unVarSet :: IntMap (SomeVariable kproxy) }++instance Show1 (Sing :: k -> *) => Show (VarSet (kproxy :: KProxy k)) where+    showsPrec p (VarSet xs) =+        showParen (p > 9)+            ( showString "VarSet "+            . showsPrec  11 xs+            )++-- | Return the successor of the largest 'varID' of all the variables+-- in the set. Thus, we return zero for the empty set and non-zero+-- for non-empty sets.+nextVarID :: VarSet kproxy -> Nat+nextVarID (VarSet xs)+    | IM.null xs = 0+    | otherwise  =+        case IM.findMax xs of+        (_, SomeVariable x) -> 1 + varID x+++emptyVarSet :: VarSet kproxy+emptyVarSet = VarSet IM.empty++singletonVarSet :: Variable a -> VarSet (KindOf a)+singletonVarSet x =+    VarSet $ IM.singleton (fromNat $ varID x) (SomeVariable x)++fromVarSet :: VarSet kproxy -> [SomeVariable kproxy]+fromVarSet (VarSet xs) = IM.elems xs++-- | Convert a list of variables into a variable set.+--+-- In the event that multiple variables have conflicting 'varID',+-- the latter variable will be kept. This generally won't matter+-- because we're treating the list as a /set/. In the cases where+-- it would matter, chances are you're going to encounter a+-- 'VarEqTypeError' sooner or later anyways.+toVarSet :: [SomeVariable kproxy] -> VarSet kproxy+toVarSet = VarSet . go IM.empty+    where+    go vars _ | vars `seq` False = error "toVarSet: the impossible happened"+    go vars []     = vars+    go vars (x:xs) = go (IM.insert (fromNat $ someVarID x) x vars) xs++    someVarID :: SomeVariable kproxy -> Nat+    someVarID (SomeVariable x) = varID x+++-- | Convert a list of variables into a variable set.+--+-- In the event that multiple variables have conflicting 'varID',+-- the latter variable will be kept. This generally won't matter+-- because we're treating the list as a /set/. In the cases where+-- it would matter, chances are you're going to encounter a+-- 'VarEqTypeError' sooner or later anyways.+toVarSet1 :: List1 Variable (xs :: [k]) -> VarSet (kproxy :: KProxy k)+toVarSet1 = toVarSet . someVariables+    where+    -- N.B., this conversion maintains the variable ordering.+    someVariables+        :: List1 Variable (xs :: [k])+        -> [SomeVariable (kproxy :: KProxy k)]+    someVariables Nil1         = []+    someVariables (Cons1 x xs) = SomeVariable x : someVariables xs+++instance Monoid (VarSet kproxy) where+    mempty = emptyVarSet+    mappend (VarSet xs) (VarSet ys) = VarSet (IM.union xs ys) -- TODO: remove bias; crash if conflicting definitions+    mconcat = VarSet . IM.unions . map unVarSet+++insertVarSet :: Variable a -> VarSet (KindOf a) -> VarSet (KindOf a)+insertVarSet x (VarSet xs) =+    case+        IM.insertLookupWithKey+            (\_ v' _ -> v')+            (fromNat $ varID x)+            (SomeVariable x)+            xs+    of+    (Nothing, xs') -> VarSet xs'+    (Just _,  _)   -> error "insertVarSet: variable is already assigned!"+++deleteVarSet :: Variable a -> VarSet (KindOf a) -> VarSet (KindOf a)+deleteVarSet x (VarSet xs) =+    --- BUG: use some sort of deleteLookupWithKey to make sure we got the right one...+    VarSet $ IM.delete (fromNat $ varID x) xs+++memberVarSet+    :: (Show1 (Sing :: k -> *), JmEq1 (Sing :: k -> *))+    => Variable (a :: k)+    -> VarSet (kproxy :: KProxy k)+    -> Bool+memberVarSet x (VarSet xs) =+    -- HACK: can't use do-notation here for GADT reasons+    case IM.lookup (fromNat $ varID x) xs of+    Nothing                -> False+    Just (SomeVariable x') -> +        case varEq x x' of+        Nothing -> False+        Just _  -> True++----------------------------------------------------------------+-- BUG: haddock doesn't like annotations on GADT constructors. So+-- here we'll avoid using the GADT syntax, even though it'd make+-- the data type declaration prettier\/cleaner.+-- <https://github.com/hakaru-dev/hakaru/issues/6>+--+-- | A pair of variable and term, both of the same Hakaru type.+data Assoc (ast :: k -> *)+    = forall (a :: k) . Assoc+        {-# UNPACK #-} !(Variable a)+        !(ast a)++instance (Show1 (Sing :: k -> *), Show1 (ast :: k -> *))+    => Show (Assoc ast)+    where+    showsPrec p (Assoc x e) =+        showParen (p > 9)+            ( showString "Assoc "+            . showsPrec1 11 x+            . showString " "+            . showsPrec1 11 e+            )+++-- BUG: since multiple 'varEq'-distinct variables could have the+-- same ID, we should really have the elements be a list of+-- associations (or something more efficient; e.g., if 'Sing' is+-- hashable).+--+-- | A set of variable\/term associations.+--+-- N.B., the current implementation assumes 'varEq' uses either the+-- second or third interpretations; that is, it is impossible to+-- have a single 'varID' be shared by multiple variables (i.e., at+-- different types). If you really want the first interpretation,+-- then the implementation must be updated.+newtype Assocs ast = Assocs { unAssocs :: IntMap (Assoc ast) }++instance (Show1 (Sing :: k -> *), Show1 (ast :: k -> *))+    => Show (Assocs ast)+    where+    showsPrec p rho =+        showParen (p > 9)+            ( showString "toAssocs "+            . showListWith shows (fromAssocs rho)+            )++-- | The empty set of associations.+emptyAssocs :: Assocs abt+emptyAssocs = Assocs IM.empty++-- | A single association.+singletonAssocs :: Variable a -> f a -> Assocs f+singletonAssocs x e =+    Assocs $ IM.singleton (fromNat $ varID x) (Assoc x e)++-- | Convert an association list into a list of associations.+fromAssocs :: Assocs ast -> [Assoc ast]+fromAssocs (Assocs rho) = IM.elems rho++-- | Convert a list of associations into an association list. In+-- the event of conflict, later associations override earlier ones.+toAssocs :: [Assoc ast] -> Assocs ast+toAssocs = Assocs . foldl step IM.empty+    where+    step :: IntMap (Assoc ast) -> Assoc ast -> IntMap (Assoc ast)+    step xes xe@(Assoc x _) = IM.insert (fromNat $ varID x) xe xes+++-- TODO: Do we also want a zipped curried variant: @List1 (Pair1 Variable ast) xs@?+-- | Convert an unzipped list of curried associations into an+-- association list. In the event of conflict, later associations+-- override earlier ones.+toAssocs1 :: List1 Variable xs -> List1 ast xs -> Assocs ast+toAssocs1 = \xs es -> Assocs (go IM.empty xs es)+    where+    go  :: IntMap (Assoc ast)+        -> List1 Variable xs+        -> List1 ast xs+        -> IntMap (Assoc ast)+    -- BUG: GHC claims the patterns are non-exhaustive here+    go m Nil1         Nil1         = m+    go m (Cons1 x xs) (Cons1 e es) =+        go (IM.insert (fromNat $ varID x) (Assoc x e) m) xs es+    go _ _ _ = error "toAssocs1: the impossible happened"+++instance Monoid (Assocs abt) where+    mempty = emptyAssocs+    mappend (Assocs xs) (Assocs ys) = Assocs (IM.union xs ys) -- TODO: remove bias; crash if conflicting definitions+    mconcat = Assocs . IM.unions . map unAssocs+++-- If we actually do have a list (etc) of variables for each ID,+-- and want to add the new binding to whatever old ones, then it+-- looks like there's no way to do that in one pass of both the+-- IntMap and the list.+--+-- | Add an association to the set of associations.+--+-- HACK: if the variable is already associated with some term then+-- we throw an error! In the future it'd be better to take some+-- sort of continuation to decide between (a) replacing the old+-- binding, (b) throwing an exception, or (c) safely wrapping the+-- result up with 'Maybe'+insertAssoc :: Assoc ast -> Assocs ast -> Assocs ast+insertAssoc v@(Assoc x _) (Assocs xs) =+    case IM.insertLookupWithKey (\_ v' _ -> v') (fromNat $ varID x) v xs of+    (Nothing, xs') -> Assocs xs'+    (Just _,  _)   -> error "insertAssoc: variable is already assigned!"++insertAssocs :: Assocs ast -> Assocs ast -> Assocs ast+insertAssocs (Assocs from) to = IM.foldr insertAssoc to from++-- | Adjust an association so existing variable refers to different+-- value. Does nothing if variable not present.+adjustAssoc :: Variable (a :: k)+            -> (Assoc ast -> Assoc ast)+            -> Assocs ast+            -> Assocs ast+adjustAssoc x f (Assocs xs) =+    Assocs $ IM.adjust f (fromNat $ varID x) xs++-- | Look up a variable and return the associated term.+--+-- N.B., this function is robust to all interpretations of 'varEq'.+lookupAssoc+    :: (Show1 (Sing :: k -> *), JmEq1 (Sing :: k -> *))+    => Variable (a :: k)+    -> Assocs ast+    -> Maybe (ast a)+lookupAssoc x (Assocs xs) = do+    Assoc x' e' <- IM.lookup (fromNat $ varID x) xs+    Refl        <- varEq x x'+    return e'+{-+-- for @Assocs abt = IntMap [Assoc abt]@ this should work:+lookupAssoc x (Assocs xss) =+    go x <$> IM.lookup (fromNat $ varID x) xss+    where+    go x []                 = Nothing+    go x (Assoc x' e' : xs) =+        case varEq x x' of+        Just Refl -> Just e'+        Nothing   -> go x xs+-}++mapAssocs :: (Assoc ast1 -> Assoc ast2) -> Assocs ast1 -> Assocs ast2+mapAssocs f (Assocs xs) = Assocs (IM.map f xs)+                ++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Types/Coercion.hs view
@@ -0,0 +1,500 @@+{-# LANGUAGE CPP+           , KindSignatures+           , DataKinds+           , GADTs+           , StandaloneDeriving+           , ExistentialQuantification+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2015.12.18+-- |+-- Module      :  Language.Hakaru.Types.Coercion+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- Our theory of coercions for Hakaru's numeric hierarchy.+----------------------------------------------------------------+module Language.Hakaru.Types.Coercion+    (+    -- * The primitive coercions+      PrimCoercion(..)+    , PrimCoerce(..)++    -- * The category of general coercions+    , Coercion(..)+    , singletonCoercion+    , signed+    , continuous+    , Coerce(..)+    , singCoerceDom+    , singCoerceCod+    , singCoerceDomCod++    -- * The induced coercion hierarchy+    , CoercionMode(..)+    , findCoercion+    , findEitherCoercion+    , Lub(..)+    , findLub+    , SomeRing(..)+    , findRing+    , SomeFractional(..)+    , findFractional++    -- * Experimental optimization functions+    {-+    , CoerceTo_UnsafeFrom(..)+    , simplifyCTUF+    , UnsafeFrom_CoerceTo(..)+    , simplifyUFCT+    -}+    , ZigZag(..)+    , simplifyZZ+    ) where++import Prelude          hiding (id, (.))+import Control.Category (Category(..))+#if __GLASGOW_HASKELL__ < 710+import Data.Functor        ((<$>))+#endif+import Control.Applicative ((<|>))+import Language.Hakaru.Types.DataKind+import Language.Hakaru.Types.Sing+import Language.Hakaru.Types.HClasses+import Language.Hakaru.Syntax.IClasses+    (TypeEq(..), Eq1(..), Eq2(..), JmEq1(..), JmEq2(..))++----------------------------------------------------------------+----------------------------------------------------------------+-- TODO: (?) coercing HMeasure by coercing the underlying measure space.+-- TODO: lifting coercion over (:->), to avoid the need for eta-expansion+-- TODO: lifting coersion over datatypes, to avoid traversing them at runtime+-- TODO: see how GHC handles lifting coersions these days...++-- N.B., we don't need to store the dictionary values here, we can recover them by typeclass (using -XScopedTypeVariables).+--+-- | Primitive proofs of the inclusions in our numeric hierarchy.+data PrimCoercion :: Hakaru -> Hakaru -> * where+    Signed     :: !(HRing a)       -> PrimCoercion (NonNegative a) a+    Continuous :: !(HContinuous a) -> PrimCoercion (HIntegral   a) a++-- TODO: instance Read (PrimCoercion a b)+deriving instance Show (PrimCoercion a b)++instance Eq (PrimCoercion a b) where -- this one could be derived+    (==) = eq1+instance Eq1 (PrimCoercion a) where+    eq1 = eq2+instance Eq2 PrimCoercion where+    eq2 x y = maybe False (const True) (jmEq2 x y)+instance JmEq1 (PrimCoercion a) where+    jmEq1 x y = snd <$> jmEq2 x y+instance JmEq2 PrimCoercion where+    jmEq2 (Signed r1) (Signed r2) =+        jmEq1 r1 r2 >>= \Refl -> Just (Refl, Refl)+    jmEq2 (Continuous c1) (Continuous c2) =+        jmEq1 c1 c2 >>= \Refl -> Just (Refl, Refl)+    jmEq2 _ _ = Nothing+++----------------------------------------------------------------+-- | General proofs of the inclusions in our numeric hierarchy.+-- Notably, being a partial order, 'Coercion' forms a category. In+-- addition to the 'Category' instance, we also have the class+-- 'Coerce' for functors from 'Coercion' to the category of Haskell+-- functions, and you can get the co\/domain objects (via+-- 'singCoerceDom', 'singCoerceCod', or 'singCoerceDomCod').+data Coercion :: Hakaru -> Hakaru -> * where+    -- BUG: haddock doesn't like annotations on GADT constructors+    -- <https://github.com/hakaru-dev/hakaru/issues/6>++    -- Added the trivial coercion so we get the Category instance.+    -- This may/should make program transformations easier to write+    -- by allowing more intermediate ASTs, but will require a cleanup+    -- pass afterwards to remove the trivial coercions.+    CNil :: Coercion a a++    -- TODO: but sometimes we need the snoc-based inductive hypothesis...+    -- We use a cons-based approach rather than append-based in+    -- order to get a better inductive hypothesis.+    CCons :: !(PrimCoercion a b) -> !(Coercion b c) -> Coercion a c++-- TODO: instance Read (Coercion a b)+deriving instance Show (Coercion a b)++instance Eq  (Coercion a b) where+    (==) = eq1+instance Eq1 (Coercion a) where+    eq1 = eq2+instance Eq2 Coercion where+    eq2 CNil         CNil         = True+    eq2 (CCons x xs) (CCons y ys) =+      case jmEq2 x y of+         Just (Refl, Refl) -> eq2 xs ys+         Nothing -> False+    eq2 _            _            = False++-- TODO: the JmEq2 and JmEq1 instances++instance Category Coercion where+    id = CNil+    xs . CNil       = xs+    xs . CCons y ys = CCons y (xs . ys)+++-- BUG: GHC 7.8 does not allow making these into pattern synonyms:+-- (1) it disallows standalone type signatures for pattern synonyms,+-- so we'd need to give it as an annotation, which isn't too terrible;+-- but, (2) it does not allow polymorphic pattern synonyms :(++-- | A smart constructor for lifting 'PrimCoercion' into 'Coercion'+singletonCoercion :: PrimCoercion a b -> Coercion a b+singletonCoercion c = CCons c CNil++-- | A smart constructor for 'Signed'.+signed :: (HRing_ a) => Coercion (NonNegative a) a+signed = singletonCoercion $ Signed hRing++-- | A smart constructor for 'Continuous'.+continuous :: (HContinuous_ a) => Coercion (HIntegral a) a+continuous = singletonCoercion $ Continuous hContinuous+++----------------------------------------------------------------+-- | This class defines a mapping from 'PrimCoercion' to the @(->)@+-- category. (Technically these mappings aren't functors, since+-- 'PrimCoercion' doesn't form a category.) It's mostly used for+-- defining the analogous 'Coerce' instance; that is, given a+-- @PrimCoerce F@ instance, we have the following canonical @Coerce+-- F@ instance:+--+-- > instance Coerce F where+-- >     coerceTo   CNil         s = s+-- >     coerceTo   (CCons c cs) s = coerceTo cs (primCoerceTo c s)+-- >+-- >     coerceFrom CNil         s = s+-- >     coerceFrom (CCons c cs) s = primCoerceFrom c (coerceFrom cs s)+--+class PrimCoerce (f :: Hakaru -> *) where+    primCoerceTo   :: PrimCoercion a b -> f a -> f b+    primCoerceFrom :: PrimCoercion a b -> f b -> f a++instance PrimCoerce (Sing :: Hakaru -> *) where+    primCoerceTo (Signed theRing) s =+        case jmEq1 s (sing_NonNegative theRing) of+        Just Refl -> sing_HRing theRing+        Nothing   -> error "primCoerceTo@Sing: the impossible happened"+    primCoerceTo (Continuous theCont) s =+        case jmEq1 s (sing_HIntegral theCont) of+        Just Refl -> sing_HContinuous theCont+        Nothing   -> error "primCoerceTo@Sing: the impossible happened"++    primCoerceFrom (Signed theRing) s =+        case jmEq1 s (sing_HRing theRing) of+        Just Refl -> sing_NonNegative theRing+        Nothing   -> error "primCoerceFrom@Sing: the impossible happened"+    primCoerceFrom (Continuous theCont) s =+        case jmEq1 s (sing_HContinuous theCont) of+        Just Refl -> sing_HIntegral theCont+        Nothing   -> error "primCoerceFrom@Sing: the impossible happened"+++-- | This class defines functors from the 'Coercion' category to+-- the @(->)@ category. It's mostly used for defining smart+-- constructors that implement the coercion in @f@. We don't require+-- a 'PrimCoerce' constraint (because we never need it), but given+-- a @Coerce F@ instance, we have the following canonical @PrimCoerce+-- F@ instance:+--+-- > instance PrimCoerce F where+-- >     primCoerceTo   c = coerceTo   (singletonCoercion c)+-- >     primCoerceFrom c = coerceFrom (singletonCoercion c)+--+class Coerce (f :: Hakaru -> *) where+    coerceTo   :: Coercion a b -> f a -> f b+    coerceFrom :: Coercion a b -> f b -> f a++instance Coerce (Sing :: Hakaru -> *) where+    coerceTo   CNil         s = s+    coerceTo   (CCons c cs) s = coerceTo cs (primCoerceTo c s)++    coerceFrom CNil         s = s+    coerceFrom (CCons c cs) s = primCoerceFrom c (coerceFrom cs s)++----------------------------------------------------------------+singPrimCoerceDom :: PrimCoercion a b -> Sing a+singPrimCoerceDom (Signed     theRing) = sing_NonNegative theRing+singPrimCoerceDom (Continuous theCont) = sing_HIntegral   theCont++singPrimCoerceCod :: PrimCoercion a b -> Sing b+singPrimCoerceCod (Signed     theRing) = sing_HRing       theRing+singPrimCoerceCod (Continuous theCont) = sing_HContinuous theCont+++-- | Return a singleton for the domain type, or 'Nothing' if it's+-- the 'CNil' coercion.+singCoerceDom :: Coercion a b -> Maybe (Sing a)+singCoerceDom CNil           = Nothing+singCoerceDom (CCons c CNil) = Just $ singPrimCoerceDom c+singCoerceDom (CCons c cs)   = primCoerceFrom c <$> singCoerceDom cs++-- | Return a singleton for the codomain type, or 'Nothing' if it's+-- the 'CNil' coercion.+singCoerceCod :: Coercion a b -> Maybe (Sing b)+singCoerceCod CNil           = Nothing+singCoerceCod (CCons c CNil) = Just $ singPrimCoerceCod c+singCoerceCod (CCons c cs)   = Just . coerceTo cs $ singPrimCoerceCod c++-- | Return singletons for the domain and codomain types, or 'Nothing'+-- if it's the 'CNil' coercion. If you need both types, this is a+-- bit more efficient than calling 'singCoerceDom' and 'singCoerceCod'+-- separately.+singCoerceDomCod :: Coercion a b -> Maybe (Sing a, Sing b)+singCoerceDomCod CNil           = Nothing+singCoerceDomCod (CCons c CNil) =+    Just (singPrimCoerceDom c, singPrimCoerceCod c)+singCoerceDomCod (CCons c cs)   = do+    dom <- singCoerceDom cs+    Just (primCoerceFrom c dom+        , coerceTo cs $ singPrimCoerceCod c+        )+++----------------------------------------------------------------+----------------------------------------------------------------++-- | Given two types, find a coercion from the first to the second,+-- or return 'Nothing' if there is no such coercion.+findCoercion :: Sing a -> Sing b -> Maybe (Coercion a b)+findCoercion SNat  SInt  = Just signed+findCoercion SProb SReal = Just signed+findCoercion SNat  SProb = Just continuous+findCoercion SInt  SReal = Just continuous+findCoercion SNat  SReal = Just (continuous . signed)+findCoercion a     b     = jmEq1 a b >>= \Refl -> Just CNil+++-- | Given two types, find a coercion where an unsafe+-- coercion, followed by a safe coercion are needed to+-- coerce the first type into the second, return otherwise+findMixedCoercion+    :: Sing a+    -> Sing b+    -> Maybe (Sing 'HNat, Coercion 'HNat a, Coercion 'HNat b)+findMixedCoercion SProb SInt  = Just (SNat, continuous, signed)+findMixedCoercion SInt  SProb = Just (SNat, signed, continuous)+findMixedCoercion _     _     = Nothing++data CoercionMode a b = +              Safe   (Coercion a b)+  |           Unsafe (Coercion b a)+  | forall c. Mixed  (Sing c, Coercion c a, Coercion c b)                ++-- | Given two types, find either a coercion from the first to the+-- second or a coercion from the second to the first, or returns+-- 'Nothing' if there is neither such coercion.+--+-- If the two types are equal, then we preferentially return the+-- @Coercion a b@. The ordering of the 'Either' is so that we+-- consider the @Coercion a b@ direction \"success\" in the 'Either'+-- monad (which also expresses our bias when the types are equal).+findEitherCoercion+    :: Sing a+    -> Sing b+    -> Maybe (CoercionMode a b)+findEitherCoercion a b =+    (Safe   <$> findCoercion a b) <|>+    (Unsafe <$> findCoercion b a) <|>+    (Mixed  <$> findMixedCoercion a b)+++-- | An upper bound of two types, with the coercions witnessing its+-- upperbound-ness. The type itself ensures that we have /some/+-- upper bound; but in practice we assume it is in fact the /least/+-- upper bound.+data Lub (a :: Hakaru) (b :: Hakaru)+    = forall c. Lub !(Sing c) !(Coercion a c) !(Coercion b c)+++-- TODO: is there any way we can reuse 'findCoercion' to DRY?+-- | Given two types, find their least upper bound.+findLub :: Sing a -> Sing b -> Maybe (Lub a b)+-- cases where @a < b@:+findLub SNat  SInt  = Just $ Lub SInt  signed CNil+findLub SProb SReal = Just $ Lub SReal signed CNil+findLub SNat  SProb = Just $ Lub SProb continuous CNil+findLub SInt  SReal = Just $ Lub SReal continuous CNil+findLub SNat  SReal = Just $ Lub SReal (continuous . signed) CNil+-- the symmetric cases where @b < a@:+findLub SInt  SNat  = Just $ Lub SInt  CNil signed+findLub SReal SProb = Just $ Lub SReal CNil signed+findLub SProb SNat  = Just $ Lub SProb CNil continuous+findLub SReal SInt  = Just $ Lub SReal CNil continuous+findLub SReal SNat  = Just $ Lub SReal CNil (continuous . signed)+-- cases where the lub is different from both @a@ and @b@:+findLub SInt  SProb = Just $ Lub SReal continuous signed+findLub SProb SInt  = Just $ Lub SReal signed continuous+-- case where @a == b@:+findLub a     b     = jmEq1 a b >>= \Refl -> Just $ Lub a CNil CNil+++data SomeRing (a :: Hakaru)+    = forall b. SomeRing !(HRing b) !(Coercion a b)++-- | Give a type, finds the smallest coercion to another+-- with a HRing instance+findRing :: Sing a -> Maybe (SomeRing a)+findRing SNat  = Just (SomeRing HRing_Int  signed)+findRing SInt  = Just (SomeRing HRing_Int  CNil)+findRing SProb = Just (SomeRing HRing_Real signed)+findRing SReal = Just (SomeRing HRing_Real CNil)+findRing _     = Nothing++data SomeFractional (a :: Hakaru)+    = forall b. SomeFractional !(HFractional b) !(Coercion a b)++-- | Give a type, finds the smallest coercion to another+-- with a HFractional instance+findFractional :: Sing a -> Maybe (SomeFractional a)+findFractional SNat  = Just (SomeFractional HFractional_Prob continuous)+findFractional SInt  = Just (SomeFractional HFractional_Real continuous)+findFractional SProb = Just (SomeFractional HFractional_Prob CNil)+findFractional SReal = Just (SomeFractional HFractional_Real CNil)+findFractional _     = Nothing+++----------------------------------------------------------------+----------------------------------------------------------------++data CoerceTo_UnsafeFrom :: Hakaru -> Hakaru -> * where+    CTUF :: !(Coercion b c) -> !(Coercion b a) -> CoerceTo_UnsafeFrom a c++-- BUG: deriving instance Eq   (CoerceTo_UnsafeFrom a b)+-- BUG: deriving instance Read (CoerceTo_UnsafeFrom a b)+deriving instance Show (CoerceTo_UnsafeFrom a b)++-- TODO: handle the fact that certain coercions commute over one another!+simplifyCTUF :: CoerceTo_UnsafeFrom a c -> CoerceTo_UnsafeFrom a c+simplifyCTUF (CTUF xs ys) =+    case xs of+    CNil        -> CTUF CNil ys+    CCons x xs' ->+        case ys of+        CNil        -> CTUF xs CNil+        CCons y ys' ->+            case jmEq2 x y of+            Just (Refl, Refl) -> simplifyCTUF (CTUF xs' ys')+            Nothing           -> CTUF xs ys++----------------------------------------------------------------+-- | Choose the other inductive hypothesis.+data RevCoercion :: Hakaru -> Hakaru -> * where+    CLin  :: RevCoercion a a+    CSnoc :: !(RevCoercion a b) -> !(PrimCoercion b c) -> RevCoercion a c++-- BUG: deriving instance Eq   (RevCoercion a b)+-- BUG: deriving instance Read (RevCoercion a b)+deriving instance Show (RevCoercion a b)++instance Category RevCoercion where+    id = CLin+    CLin . xs       = xs+    CSnoc ys y . xs = CSnoc (ys . xs) y++revCons :: PrimCoercion a b -> RevCoercion b c -> RevCoercion a c+revCons x CLin         = CSnoc CLin x+revCons x (CSnoc ys y) = CSnoc (revCons x ys) y++toRev :: Coercion a b -> RevCoercion a b+toRev CNil         = CLin+toRev (CCons x xs) = revCons x (toRev xs)++obvSnoc :: Coercion a b -> PrimCoercion b c -> Coercion a c+obvSnoc CNil         y = CCons y CNil+obvSnoc (CCons x xs) y = CCons x (obvSnoc xs y)++fromRev :: RevCoercion a b -> Coercion a b+fromRev CLin         = CNil+fromRev (CSnoc xs x) = obvSnoc (fromRev xs) x++data UnsafeFrom_CoerceTo :: Hakaru -> Hakaru -> * where+    UFCT+        :: !(Coercion c b)+        -> !(Coercion a b)+        -> UnsafeFrom_CoerceTo a c++-- BUG: deriving instance Eq   (UnsafeFrom_CoerceTo a b)+-- BUG: deriving instance Read (UnsafeFrom_CoerceTo a b)+deriving instance Show (UnsafeFrom_CoerceTo a b)++data RevUFCT :: Hakaru -> Hakaru -> * where+    RevUFCT :: !(RevCoercion c b) -> !(RevCoercion a b) -> RevUFCT a c+        +-- TODO: handle the fact that certain coercions commute over one another!+-- N.B., This version can be tricky to get to type check because our associated type families aren't guaranteed injective.+simplifyUFCT :: UnsafeFrom_CoerceTo a c -> UnsafeFrom_CoerceTo a c+simplifyUFCT (UFCT xs ys) =+    case simplifyRevUFCT $ RevUFCT (toRev xs) (toRev ys) of+    RevUFCT xs' ys' -> UFCT (fromRev xs') (fromRev ys')++simplifyRevUFCT :: RevUFCT a c -> RevUFCT a c+simplifyRevUFCT (RevUFCT xs ys) =+    case xs of+    CLin        -> RevUFCT CLin ys+    CSnoc xs' x ->+        case ys of+        CLin        -> RevUFCT xs CLin+        CSnoc ys' y ->+            case jmEq2 x y of+            Just (Refl, Refl) -> simplifyRevUFCT (RevUFCT xs' ys')+            Nothing           -> RevUFCT xs ys+++-- TODO: implement a simplifying pass for pushing/gathering coersions over other things (e.g., Less/Equal)++----------------------------------------------------------------+----------------------------------------------------------------++-- | An arbitrary composition of safe and unsafe coercions.+data ZigZag :: Hakaru -> Hakaru -> * where+    ZRefl :: ZigZag a a+    Zig   :: !(Coercion a b) -> !(ZigZag b c) -> ZigZag a c+    Zag   :: !(Coercion b a) -> !(ZigZag b c) -> ZigZag a c++-- BUG: deriving instance Eq   (ZigZag a b)+-- BUG: deriving instance Read (ZigZag a b)+deriving instance Show (ZigZag a b)++-- TODO: whenever we build up a new ZigZag from the remains of a simplification step, do we need to resimplify? If so, how can we avoid quadratic behavior? cf., <http://research.microsoft.com/en-us/um/people/simonpj/papers/ext-f/fc-normalization-rta.pdf> Also, try just doing a shortest-path problem on the graph of coercions (since we can get all the singletons along the way)+-- TODO: handle the fact that certain coercions commute over one another!+simplifyZZ :: ZigZag a b -> ZigZag a b+simplifyZZ ZRefl      = ZRefl+simplifyZZ (Zig x xs) =+    case simplifyZZ xs of+    ZRefl   -> Zig x ZRefl+    Zig y z -> Zig (y . x) z+    Zag y z ->+        -- TODO: can we optimize this to avoid reversing things?+        case simplifyUFCT (UFCT x y) of+        UFCT CNil CNil -> z+        UFCT CNil y'   -> Zag y' z+        UFCT x'   CNil -> Zig x' z+        UFCT x'   y'   -> Zig x' (Zag y' z)+simplifyZZ (Zag x xs) =+    case simplifyZZ xs of+    ZRefl   -> Zag x ZRefl+    Zag y z -> Zag (x . y) z+    Zig y z ->+        case simplifyCTUF (CTUF x y) of+        CTUF CNil CNil -> z+        CTUF CNil y'   -> Zig y' z+        CTUF x'   CNil -> Zag x' z+        CTUF x'   y'   -> Zag x' (Zig y' z)++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Types/DataKind.hs view
@@ -0,0 +1,176 @@+{-# LANGUAGE DataKinds+           , PolyKinds+           , TypeOperators+           , TypeFamilies+           , StandaloneDeriving+           , DeriveDataTypeable+           , ScopedTypeVariables+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.05.28+-- |+-- Module      :  Language.Hakaru.Types.DataKind+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- A data-kind for the universe of Hakaru types.+----------------------------------------------------------------+module Language.Hakaru.Types.DataKind+    (+    -- * The core definition of Hakaru types+      Hakaru(..)+    , HakaruFun(..)+    , HakaruCon(..) +    -- *+    , Symbol+    , Code+    , HData'+    -- * Some \"built-in\" types+    -- Naturally, these aren't actually built-in, otherwise they'd+    -- be part of the 'Hakaru' data-kind.+    , HBool, HUnit, HPair, HEither, HList, HMaybe+    ) where++import Data.Typeable (Typeable)+import GHC.TypeLits (Symbol)++----------------------------------------------------------------+-- BUG: can't define the fixity of @(':->)@+infixr 0 :->++-- | The universe\/kind of Hakaru types.+data Hakaru+    = HNat -- ^ The natural numbers; aka, the non-negative integers.++    -- TODO: in terms of Summate (etc), do we consider this to include omega?+    -- | The integers.+    | HInt++    -- | Non-negative real numbers. Unlike what you might expect,+    -- this is /not/ restructed to the @[0,1]@ interval!+    | HProb++    -- | The affinely extended real number line. That is, the real+    -- numbers extended with positive and negative infinities.+    | HReal++    -- TODO: so much of our code has to distinguish between monadic and pure stuff. Maybe we should just break this out into a separate larger universe?+    -- | The measure monad+    | HMeasure !Hakaru++    -- | The built-in type for uniform arrays.+    | HArray !Hakaru++    -- | The type of Hakaru functions.+    | !Hakaru :-> !Hakaru++    -- TODO: do we need to actually store the code? or can we get away with just requiring that the particular HakaruCon has a Code instance defined?+    -- | A user-defined polynomial datatype. Each such type is+    -- specified by a \"tag\" (the @HakaruCon@) which names the type, and a sum-of-product representation of the type itself.+    | HData !HakaruCon [[HakaruFun]]+++-- N.B., The @Proxy@ type from "Data.Proxy" is polykinded, so it+-- works for @Hakaru@ too. However, it is _not_ Typeable!+--+-- TODO: all the Typeable instances in this file are only used in+-- 'Language.Hakaru.Simplify.closeLoop'; it would be cleaner to+-- remove these instances and reimplement that function to work+-- without them.++deriving instance Typeable 'HNat+deriving instance Typeable 'HInt+deriving instance Typeable 'HProb+deriving instance Typeable 'HReal+deriving instance Typeable 'HMeasure+deriving instance Typeable 'HArray+deriving instance Typeable '(:->)+deriving instance Typeable 'HData+++----------------------------------------------------------------+-- | The identity and constant functors on 'Hakaru'. This gives+-- us limited access to type-variables in @Hakaru@, for use in+-- recursive sums-of-products. Notably, however, it only allows a+-- single variable (namely the one bound by the closest binder) so+-- it can't encode mutual recursion or other non-local uses of+-- multiple binders. We also cannot encode non-regular recursive+-- types (aka nested datatypes), like rose trees. To do that, we'd+-- need to allow any old functor here.+--+-- Products and sums are represented as lists in the 'Hakaru'+-- data-kind itself, so they aren't in this datatype.+data HakaruFun = I | K !Hakaru++deriving instance Typeable 'I+deriving instance Typeable 'K+++----------------------------------------------------------------+-- | The kind of user-defined Hakaru type constructors, which serves+-- as a tag for the sum-of-products representation of the user-defined+-- Hakaru type. The head of the 'HakaruCon' is a symbolic name, and+-- the rest are arguments to that type constructor. The @a@ parameter+-- is parametric, which is especially useful when you need a singleton+-- of the constructor. The argument positions are necessary to do+-- variable binding in Code. 'Symbol' is the kind of \"type level+-- strings\".+data HakaruCon = TyCon !Symbol | HakaruCon :@ Hakaru+infixl 0 :@++deriving instance Typeable 'TyCon+deriving instance Typeable '(:@)+++-- | The Code type family allows users to extend the Hakaru language+-- by adding new types. The right hand side is the sum-of-products+-- representation of that type. See the \"built-in\" types for examples.+type family   Code (a :: HakaruCon) :: [[HakaruFun]]+type instance Code ('TyCon "Bool")               = '[ '[], '[] ]+type instance Code ('TyCon "Unit")               = '[ '[] ]+type instance Code ('TyCon "Maybe"  ':@ a)       = '[ '[] , '[ 'K a ] ]+type instance Code ('TyCon "List"   ':@ a)       = '[ '[] , '[ 'K a, 'I ] ]+type instance Code ('TyCon "Pair"   ':@ a ':@ b) = '[ '[ 'K a, 'K b ] ]+type instance Code ('TyCon "Either" ':@ a ':@ b) = '[ '[ 'K a ], '[ 'K b ] ]+++-- | A helper type alias for simplifying type signatures for+-- user-provided Hakaru types.+--+-- BUG: you cannot use this alias when defining other type aliases!+-- For some reason the type checker doesn't reduce the type family+-- applications, which prevents the use of these type synonyms in+-- class instance heads. Any type synonym created with 'HData''+-- will suffer the same issue, so type synonyms must be written out+-- by hand— or copied from the GHC pretty printer, which will happily+-- reduce things in the repl, even in the presence of quantified+-- type variables.+type HData' t = 'HData t (Code t)+{-+   >:kind! forall a b . HData' (TyCon "Pair" :@ a :@ b)+   forall a b . HData' (TyCon "Pair" :@ a :@ b) :: Hakaru+   = forall (a :: Hakaru) (b :: Hakaru).+     'HData (('TyCon "Pair" ':@ a) ':@ b) '['['K a, 'K b]]++type HBool       = HData' (TyCon "Bool")+type HUnit       = HData' (TyCon "Unit")+type HPair   a b = HData' (TyCon "Pair"   :@ a :@ b)+type HEither a b = HData' (TyCon "Either" :@ a :@ b)+type HList   a   = HData' (TyCon "List"   :@ a)+type HMaybe  a   = HData' (TyCon "Maybe"  :@ a)+-}++type HBool       = 'HData ('TyCon "Bool") '[ '[], '[] ]+type HUnit       = 'HData ('TyCon "Unit") '[ '[] ]+type HPair   a b = 'HData ('TyCon "Pair"   ':@ a ':@ b) '[ '[ 'K a, 'K b] ]+type HEither a b = 'HData ('TyCon "Either" ':@ a ':@ b) '[ '[ 'K a], '[ 'K b] ]+type HList   a   = 'HData ('TyCon "List"    ':@ a) '[ '[], '[ 'K a, 'I] ]+type HMaybe  a   = 'HData ('TyCon "Maybe"   ':@ a) '[ '[], '[ 'K a] ]++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Types/HClasses.hs view
@@ -0,0 +1,606 @@+{-# LANGUAGE CPP+           , GADTs+           , KindSignatures+           , DataKinds+           , PolyKinds+           , TypeFamilies+           , FlexibleContexts+           , FlexibleInstances+           , TypeSynonymInstances+           , StandaloneDeriving+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2015.12.15+-- |+-- Module      :  Language.Hakaru.Types.HClasses+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- A collection of type classes for encoding Hakaru's numeric hierarchy.+----------------------------------------------------------------+module Language.Hakaru.Types.HClasses+    (+    -- * Equality+      HEq(..)+    , HEq_(..)+    , sing_HEq+    , hEq_Sing++    -- * Ordering+    , HOrd(..)+    , hEq_HOrd+    , HOrd_(..)+    , sing_HOrd+    , hOrd_Sing++   -- * HIntegrable+    , HIntegrable(..)+    , sing_HIntegrable+    , hIntegrable_Sing++    -- * Semirings+    , HSemiring(..)+    , HSemiring_(..)+    , sing_HSemiring+    , hSemiring_Sing++    -- * Rings+    , HRing(..)+    , hSemiring_HRing+    , hSemiring_NonNegativeHRing+    , HRing_(..)+    , sing_HRing+    , hRing_Sing+    , sing_NonNegative++    -- * Fractional types+    , HFractional(..)+    , hSemiring_HFractional+    , HFractional_(..)+    , sing_HFractional+    , hFractional_Sing++    -- * Radical types+    , HRadical(..)+    , hSemiring_HRadical+    , HRadical_(..)+    , sing_HRadical+    , hRadical_Sing++   -- * Discrete types+    , HDiscrete(..)+    , HDiscrete_(..)+    , sing_HDiscrete+    , hDiscrete_Sing++    -- * Continuous types+    , HContinuous(..)+    , hFractional_HContinuous+    , hSemiring_HIntegralContinuous+    , HContinuous_(..)+    , sing_HContinuous+    , hContinuous_Sing+    , sing_HIntegral+    ) where++#if __GLASGOW_HASKELL__ < 710+import Data.Functor ((<$>))+#endif+import Control.Applicative ((<|>))+import Language.Hakaru.Syntax.IClasses (TypeEq(..), Eq1(..), JmEq1(..))+import Language.Hakaru.Types.DataKind+import Language.Hakaru.Types.Sing++----------------------------------------------------------------+-- | Concrete dictionaries for Hakaru types with decidable equality.+data HEq :: Hakaru -> * where+    HEq_Nat    :: HEq 'HNat+    HEq_Int    :: HEq 'HInt+    HEq_Prob   :: HEq 'HProb+    HEq_Real   :: HEq 'HReal+    HEq_Array  :: !(HEq a) -> HEq ('HArray a)+    HEq_Bool   :: HEq HBool+    HEq_Unit   :: HEq HUnit+    HEq_Pair   :: !(HEq a) -> !(HEq b) -> HEq (HPair   a b)+    HEq_Either :: !(HEq a) -> !(HEq b) -> HEq (HEither a b)++deriving instance Eq   (HEq a)+-- TODO: instance JmEq1 HEq+-- BUG: deriving instance Read (HEq a)+deriving instance Show (HEq a)++-- N.B., we do case analysis so that we don't need the class constraint!+sing_HEq :: HEq a -> Sing a+sing_HEq HEq_Nat          = SNat+sing_HEq HEq_Int          = SInt+sing_HEq HEq_Prob         = SProb+sing_HEq HEq_Real         = SReal+sing_HEq (HEq_Array  a)   = SArray  (sing_HEq a)+sing_HEq HEq_Bool         = sBool+sing_HEq HEq_Unit         = sUnit+sing_HEq (HEq_Pair   a b) = sPair   (sing_HEq a) (sing_HEq b)+sing_HEq (HEq_Either a b) = sEither (sing_HEq a) (sing_HEq b)++hEq_Sing :: Sing a -> Maybe (HEq a)+hEq_Sing SNat        = Just HEq_Nat+hEq_Sing SInt        = Just HEq_Int+hEq_Sing SProb       = Just HEq_Prob+hEq_Sing SReal       = Just HEq_Real+hEq_Sing (SArray a)  = HEq_Array <$> hEq_Sing a+hEq_Sing s           = (jmEq1 s sUnit  >>= \Refl -> Just HEq_Unit) <|>+                       (jmEq1 s sBool  >>= \Refl -> Just HEq_Bool)+{-+hEq_Sing (sPair   a b) = HEq_Pair <$> hEq_Sing a <*> hEq_Sing b+hEq_Sing (sEither a b) = HEq_Either <$> hEq_Sing a <*> hEq_Sing b+-}++-- | Haskell type class for automatic 'HEq' inference.+class    HEq_ (a :: Hakaru) where hEq :: HEq a+instance HEq_ 'HNat         where hEq = HEq_Nat +instance HEq_ 'HInt         where hEq = HEq_Int +instance HEq_ 'HProb        where hEq = HEq_Prob +instance HEq_ 'HReal        where hEq = HEq_Real +instance HEq_ HBool         where hEq = HEq_Bool +instance HEq_ HUnit         where hEq = HEq_Unit +instance (HEq_ a) => HEq_ ('HArray a) where+    hEq = HEq_Array hEq+instance (HEq_ a, HEq_ b) => HEq_ (HPair a b) where+    hEq = HEq_Pair hEq hEq+instance (HEq_ a, HEq_ b) => HEq_ (HEither a b) where+    hEq = HEq_Either hEq hEq+++----------------------------------------------------------------+-- | Concrete dictionaries for Hakaru types with decidable total ordering.+data HOrd :: Hakaru -> * where+    HOrd_Nat    :: HOrd 'HNat+    HOrd_Int    :: HOrd 'HInt+    HOrd_Prob   :: HOrd 'HProb+    HOrd_Real   :: HOrd 'HReal+    HOrd_Array  :: !(HOrd a) -> HOrd ('HArray a)+    HOrd_Bool   :: HOrd HBool+    HOrd_Unit   :: HOrd HUnit+    HOrd_Pair   :: !(HOrd a) -> !(HOrd b) -> HOrd (HPair   a b)+    HOrd_Either :: !(HOrd a) -> !(HOrd b) -> HOrd (HEither a b)++deriving instance Eq   (HOrd a)+-- TODO: instance JmEq1 HOrd+-- BUG: deriving instance Read (HOrd a)+deriving instance Show (HOrd a)++sing_HOrd :: HOrd a -> Sing a+sing_HOrd HOrd_Nat          = SNat+sing_HOrd HOrd_Int          = SInt+sing_HOrd HOrd_Prob         = SProb+sing_HOrd HOrd_Real         = SReal+sing_HOrd (HOrd_Array  a)   = SArray  (sing_HOrd a)+sing_HOrd HOrd_Bool         = sBool+sing_HOrd HOrd_Unit         = sUnit+sing_HOrd (HOrd_Pair   a b) = sPair   (sing_HOrd a) (sing_HOrd b)+sing_HOrd (HOrd_Either a b) = sEither (sing_HOrd a) (sing_HOrd b)++hOrd_Sing :: Sing a -> Maybe (HOrd a)+hOrd_Sing SNat              = Just HOrd_Nat+hOrd_Sing SInt              = Just HOrd_Int+hOrd_Sing SProb             = Just HOrd_Prob+hOrd_Sing SReal             = Just HOrd_Real+hOrd_Sing (SArray a)        = HOrd_Array <$> hOrd_Sing a+hOrd_Sing _                 = Nothing++-- | Every 'HOrd' type is 'HEq'.+hEq_HOrd :: HOrd a -> HEq a+hEq_HOrd HOrd_Nat          = HEq_Nat+hEq_HOrd HOrd_Int          = HEq_Int+hEq_HOrd HOrd_Prob         = HEq_Prob+hEq_HOrd HOrd_Real         = HEq_Real+hEq_HOrd (HOrd_Array  a)   = HEq_Array  (hEq_HOrd a)+hEq_HOrd HOrd_Bool         = HEq_Bool+hEq_HOrd HOrd_Unit         = HEq_Unit+hEq_HOrd (HOrd_Pair   a b) = HEq_Pair   (hEq_HOrd a) (hEq_HOrd b)+hEq_HOrd (HOrd_Either a b) = HEq_Either (hEq_HOrd a) (hEq_HOrd b)++-- | Haskell type class for automatic 'HOrd' inference.+class    HEq_ a => HOrd_ (a :: Hakaru) where hOrd :: HOrd a+instance HOrd_ 'HNat                   where hOrd = HOrd_Nat +instance HOrd_ 'HInt                   where hOrd = HOrd_Int +instance HOrd_ 'HProb                  where hOrd = HOrd_Prob +instance HOrd_ 'HReal                  where hOrd = HOrd_Real +instance HOrd_ HBool                   where hOrd = HOrd_Bool +instance HOrd_ HUnit                   where hOrd = HOrd_Unit +instance (HOrd_ a) => HOrd_ ('HArray a) where+    hOrd = HOrd_Array hOrd+instance (HOrd_ a, HOrd_ b) => HOrd_ (HPair a b) where+    hOrd = HOrd_Pair hOrd hOrd+instance (HOrd_ a, HOrd_ b) => HOrd_ (HEither a b) where+    hOrd = HOrd_Either hOrd hOrd+++-- TODO: class HPER (a :: Hakaru)+-- TODO: class HPartialOrder (a :: Hakaru)++----------------------------------------------------------------+-- | Concrete dictionaries for Hakaru types which are semirings.+-- N.B., even though these particular semirings are commutative,+-- we don't necessarily assume that.+data HSemiring :: Hakaru -> * where+    HSemiring_Nat  :: HSemiring 'HNat+    HSemiring_Int  :: HSemiring 'HInt+    HSemiring_Prob :: HSemiring 'HProb+    HSemiring_Real :: HSemiring 'HReal+++instance Eq (HSemiring a) where -- This one could be derived...+    (==) = eq1+instance Eq1 HSemiring where+    eq1 x y = maybe False (const True) (jmEq1 x y)+instance JmEq1 HSemiring where+    jmEq1 HSemiring_Nat  HSemiring_Nat  = Just Refl+    jmEq1 HSemiring_Int  HSemiring_Int  = Just Refl+    jmEq1 HSemiring_Prob HSemiring_Prob = Just Refl+    jmEq1 HSemiring_Real HSemiring_Real = Just Refl+    jmEq1 _              _              = Nothing++-- BUG: deriving instance Read (HSemiring a)+deriving instance Show (HSemiring a)++sing_HSemiring :: HSemiring a -> Sing a+sing_HSemiring HSemiring_Nat  = SNat+sing_HSemiring HSemiring_Int  = SInt+sing_HSemiring HSemiring_Prob = SProb+sing_HSemiring HSemiring_Real = SReal++hSemiring_Sing :: Sing a -> Maybe (HSemiring a)+hSemiring_Sing SNat  = Just HSemiring_Nat +hSemiring_Sing SInt  = Just HSemiring_Int +hSemiring_Sing SProb = Just HSemiring_Prob+hSemiring_Sing SReal = Just HSemiring_Real+hSemiring_Sing _     = Nothing++-- | Haskell type class for automatic 'HSemiring' inference.+class    HSemiring_ (a :: Hakaru) where hSemiring :: HSemiring a+instance HSemiring_ 'HNat  where hSemiring = HSemiring_Nat +instance HSemiring_ 'HInt  where hSemiring = HSemiring_Int +instance HSemiring_ 'HProb where hSemiring = HSemiring_Prob +instance HSemiring_ 'HReal where hSemiring = HSemiring_Real +++----------------------------------------------------------------+-- | Concrete dictionaries for Hakaru types which are rings. N.B.,+-- even though these particular rings are commutative, we don't+-- necessarily assume that.+data HRing :: Hakaru -> * where+    HRing_Int  :: HRing 'HInt+    HRing_Real :: HRing 'HReal+++instance Eq (HRing a) where -- This one could be derived...+    (==) = eq1+instance Eq1 HRing where+    eq1 x y = maybe False (const True) (jmEq1 x y)+instance JmEq1 HRing where+    jmEq1 HRing_Int  HRing_Int  = Just Refl+    jmEq1 HRing_Real HRing_Real = Just Refl+    jmEq1 _          _          = Nothing++    +-- BUG: deriving instance Read (HRing a)++deriving instance Show (HRing a)++sing_HRing :: HRing a -> Sing a+sing_HRing HRing_Int  = SInt+sing_HRing HRing_Real = SReal++hRing_Sing :: Sing a -> Maybe (HRing a)+hRing_Sing SInt  = Just HRing_Int+hRing_Sing SReal = Just HRing_Real+hRing_Sing _     = Nothing++sing_NonNegative :: HRing a -> Sing (NonNegative a)+sing_NonNegative = sing_HSemiring . hSemiring_NonNegativeHRing++-- hNonNegative_Sing :: Sing (NonNegative a) -> Maybe (HRing a)++-- | Every 'HRing' is a 'HSemiring'.+hSemiring_HRing :: HRing a -> HSemiring a+hSemiring_HRing HRing_Int  = HSemiring_Int+hSemiring_HRing HRing_Real = HSemiring_Real++-- | The non-negative type of every 'HRing' is a 'HSemiring'.+hSemiring_NonNegativeHRing :: HRing a -> HSemiring (NonNegative a)+hSemiring_NonNegativeHRing HRing_Int  = HSemiring_Nat+hSemiring_NonNegativeHRing HRing_Real = HSemiring_Prob++-- | Haskell type class for automatic 'HRing' inference.+--+-- Every 'HRing' has an associated type for the semiring of its+-- non-negative elements. This type family captures two notions.+-- First, if we take the semiring and close it under negation\/subtraction+-- then we will generate this ring. Second, when we take the absolute+-- value of something in the ring we will get back something in the+-- non-negative semiring. For 'HInt' and 'HReal' these two notions+-- coincide; however for Complex and Vector types, the notions+-- diverge.+--+-- TODO: Can we somehow specify that the @HSemiring (NonNegative+-- a)@ semantics coincides with the @HSemiring a@ semantics? Or+-- should we just assume that?+class (HSemiring_ (NonNegative a), HSemiring_ a) => HRing_ (a :: Hakaru)+    where+    type NonNegative (a :: Hakaru) :: Hakaru+    hRing :: HRing a++instance HRing_ 'HInt where+    type NonNegative 'HInt = 'HNat+    hRing = HRing_Int++instance HRing_ 'HReal where+    type NonNegative 'HReal = 'HProb+    hRing = HRing_Real++++----------------------------------------------------------------+-- N.B., We're assuming two-sided inverses here. That doesn't entail+-- commutativity, though it does strongly suggest it... (cf.,+-- Wedderburn's little theorem)+--+-- N.B., the (Nat,"+"=lcm,"*"=gcd) semiring is sometimes called+-- "the division semiring"+--+-- HACK: tracking the generating carriers here wouldn't be quite+-- right b/c we get more than just the (non-negative)rationals+-- generated from HNat/HInt! However, we should have some sort of+-- associated type so we can add rationals and non-negative+-- rationals...+--+-- TODO: associated type for non-zero elements. To guarantee the+-- safety of division\/recip? For now, we have Infinity, so it's+-- actually safe for these two types. But if we want to add the+-- rationals...+--+-- | Concrete dictionaries for Hakaru types which are division-semirings;+-- i.e., division-rings without negation. This is called a \"semifield\"+-- in ring theory, but should not be confused with the \"semifields\"+-- of geometry.+data HFractional :: Hakaru -> * where+    HFractional_Prob :: HFractional 'HProb+    HFractional_Real :: HFractional 'HReal+++instance Eq (HFractional a) where -- This one could be derived...+    (==) = eq1+instance Eq1 HFractional where+    eq1 x y = maybe False (const True) (jmEq1 x y)+instance JmEq1 HFractional where+    jmEq1 HFractional_Prob HFractional_Prob = Just Refl+    jmEq1 HFractional_Real HFractional_Real = Just Refl+    jmEq1 _                _                = Nothing++-- BUG: deriving instance Read (HFractional a)+deriving instance Show (HFractional a)++sing_HFractional :: HFractional a -> Sing a+sing_HFractional HFractional_Prob = SProb+sing_HFractional HFractional_Real = SReal++hFractional_Sing :: Sing a -> Maybe (HFractional a)+hFractional_Sing SProb = Just HFractional_Prob+hFractional_Sing SReal = Just HFractional_Real+hFractional_Sing _     = Nothing++-- | Every 'HFractional' is a 'HSemiring'.+hSemiring_HFractional :: HFractional a -> HSemiring a+hSemiring_HFractional HFractional_Prob = HSemiring_Prob+hSemiring_HFractional HFractional_Real = HSemiring_Real++-- | Haskell type class for automatic 'HFractional' inference.+class (HSemiring_ a) => HFractional_ (a :: Hakaru) where+    hFractional :: HFractional a+instance HFractional_ 'HProb where hFractional = HFractional_Prob +instance HFractional_ 'HReal where hFractional = HFractional_Real +++-- type HDivisionRing a = (HFractional a, HRing a)+-- type HField a = (HDivisionRing a, HCommutativeSemiring a)+++----------------------------------------------------------------+-- Numbers formed by finitely many uses of integer addition,+-- subtraction, multiplication, division, and nat-roots are all+-- algebraic; however, N.B., not all algebraic numbers can be formed+-- this way (cf., Abel–Ruffini theorem)+-- TODO: ought we require HFractional rather than HSemiring?+-- TODO: any special associated type?+--+-- | Concrete dictionaries for semirings which are closed under all+-- 'HNat'-roots. This means it's closed under all positive rational+-- powers as well. (If the type happens to be 'HFractional', then+-- it's closed under /all/ rational powers.)+--+-- N.B., 'HReal' is not 'HRadical' because we do not have real-valued+-- roots for negative reals.+--+-- N.B., we assume not only that the type is surd-complete, but+-- also that it's still complete under the semiring operations.+-- Thus we have values like @sqrt 2 + sqrt 3@ which cannot be+-- expressed as a single root. Thus, in order to solve for zeros\/roots,+-- we'll need solutions to more general polynomials than just the+-- @x^n - a@ polynomials. However, the Galois groups of these are+-- all solvable, so this shouldn't be too bad.+data HRadical :: Hakaru -> * where+    HRadical_Prob :: HRadical 'HProb+++instance Eq (HRadical a) where -- This one could be derived...+    (==) = eq1+instance Eq1 HRadical where+    eq1 x y = maybe False (const True) (jmEq1 x y)+instance JmEq1 HRadical where+    jmEq1 HRadical_Prob HRadical_Prob = Just Refl++-- BUG: deriving instance Read (HRadical a)+deriving instance Show (HRadical a)++sing_HRadical :: HRadical a -> Sing a+sing_HRadical HRadical_Prob = SProb++hRadical_Sing :: Sing a -> Maybe (HRadical a)+hRadical_Sing SProb = Just HRadical_Prob+hRadical_Sing _     = Nothing++-- | Every 'HRadical' is a 'HSemiring'.+hSemiring_HRadical :: HRadical a -> HSemiring a+hSemiring_HRadical HRadical_Prob = HSemiring_Prob++-- | Haskell type class for automatic 'HRadical' inference.+class (HSemiring_ a) => HRadical_ (a :: Hakaru) where+    hRadical :: HRadical a+instance HRadical_ 'HProb where hRadical = HRadical_Prob +++-- TODO: class (HDivisionRing a, HRadical a) => HAlgebraic a where...++-- | Concrete dictionaries for types where Infinity can have+data HIntegrable :: Hakaru -> * where+    HIntegrable_Nat  :: HIntegrable 'HNat+    HIntegrable_Prob :: HIntegrable 'HProb++instance Eq (HIntegrable a) where -- This one could be derived...+    (==) = eq1+instance Eq1 HIntegrable where+    eq1 x y = maybe False (const True) (jmEq1 x y)+instance JmEq1 HIntegrable where+    jmEq1 HIntegrable_Nat  HIntegrable_Nat  = Just Refl+    jmEq1 HIntegrable_Prob HIntegrable_Prob = Just Refl+    jmEq1 _             _                   = Nothing++-- BUG: deriving instance Read (HIntegrable a)+deriving instance Show (HIntegrable a)++sing_HIntegrable :: HIntegrable a -> Sing a+sing_HIntegrable HIntegrable_Nat  = SNat+sing_HIntegrable HIntegrable_Prob = SProb++hIntegrable_Sing :: Sing a -> Maybe (HIntegrable a)+hIntegrable_Sing SNat  = Just HIntegrable_Nat+hIntegrable_Sing SProb = Just HIntegrable_Prob+hIntegrable_Sing _     = Nothing++-- | Concrete dictionaries for Hakaru types which are \"discrete\".+data HDiscrete :: Hakaru -> * where+    HDiscrete_Nat :: HDiscrete 'HNat+    HDiscrete_Int :: HDiscrete 'HInt++instance Eq (HDiscrete a) where -- This one could be derived...+    (==) = eq1+instance Eq1 HDiscrete where+    eq1 x y = maybe False (const True) (jmEq1 x y)+instance JmEq1 HDiscrete where+    jmEq1 HDiscrete_Nat HDiscrete_Nat = Just Refl+    jmEq1 HDiscrete_Int HDiscrete_Int = Just Refl+    jmEq1 _             _             = Nothing++-- BUG: deriving instance Read (HDiscrete a)+deriving instance Show (HDiscrete a)++sing_HDiscrete :: HDiscrete a -> Sing a+sing_HDiscrete HDiscrete_Nat = SNat+sing_HDiscrete HDiscrete_Int = SInt++hDiscrete_Sing :: Sing a -> Maybe (HDiscrete a)+hDiscrete_Sing SNat = Just HDiscrete_Nat+hDiscrete_Sing SInt = Just HDiscrete_Int+hDiscrete_Sing _    = Nothing++-- | Haskell type class for automatic 'HDiscrete' inference.+class (HSemiring_ a) => HDiscrete_ (a :: Hakaru) where+    hDiscrete :: HDiscrete a+instance HDiscrete_ 'HNat where hDiscrete = HDiscrete_Nat +instance HDiscrete_ 'HInt where hDiscrete = HDiscrete_Int ++----------------------------------------------------------------+-- TODO: find better names than HContinuous and HIntegral+-- TODO: how to require that "if HRing a, then HRing b too"?+-- TODO: should we call this something like Dedekind-complete?+-- That's what distinguishes the reals from the rationals. Of course,+-- calling it that suggests (but does not require) that we should+-- have some supremum operator; but supremum only differs from+-- maximum if we have some way of talking about infinite sets of+-- values (which is surely too much to bother with).+--+-- | Concrete dictionaries for Hakaru types which are \"continuous\".+-- This is an ad-hoc class for (a) lifting 'HNat'\/'HInt' into+-- 'HProb'\/'HReal', and (b) handling the polymorphism of monotonic+-- functions like @etf@.+data HContinuous :: Hakaru -> * where+    HContinuous_Prob :: HContinuous 'HProb+    HContinuous_Real :: HContinuous 'HReal+++instance Eq (HContinuous a) where -- This one could be derived...+    (==) = eq1+instance Eq1 HContinuous where+    eq1 x y = maybe False (const True) (jmEq1 x y)+instance JmEq1 HContinuous where+    jmEq1 HContinuous_Prob HContinuous_Prob = Just Refl+    jmEq1 HContinuous_Real HContinuous_Real = Just Refl+    jmEq1 _                _                = Nothing++-- BUG: deriving instance Read (HContinuous a)+deriving instance Show (HContinuous a)++sing_HContinuous :: HContinuous a -> Sing a+sing_HContinuous HContinuous_Prob = SProb+sing_HContinuous HContinuous_Real = SReal++hContinuous_Sing :: Sing a -> Maybe (HContinuous a)+hContinuous_Sing SProb = Just HContinuous_Prob+hContinuous_Sing SReal = Just HContinuous_Real+hContinuous_Sing _     = Nothing++sing_HIntegral :: HContinuous a -> Sing (HIntegral a)+sing_HIntegral = sing_HSemiring . hSemiring_HIntegralContinuous++-- hIntegral_Sing :: Sing (HIntegral a) -> Maybe (HContinuous a)++-- | Every 'HContinuous' is a 'HFractional'.+hFractional_HContinuous :: HContinuous a -> HFractional a+hFractional_HContinuous HContinuous_Prob = HFractional_Prob+hFractional_HContinuous HContinuous_Real = HFractional_Real++-- | The integral type of every 'HContinuous' is a 'HSemiring'.+hSemiring_HIntegralContinuous :: HContinuous a -> HSemiring (HIntegral a)+hSemiring_HIntegralContinuous HContinuous_Prob = HSemiring_Nat+hSemiring_HIntegralContinuous HContinuous_Real = HSemiring_Int++-- | Haskell type class for automatic 'HContinuous' inference.+--+-- Every 'HContinuous' has an associated type for the semiring of+-- its integral elements.+--+-- TODO: Can we somehow specify that the @HSemiring (HIntegral a)@+-- semantics coincides with the @HSemiring a@ semantics? Or should+-- we just assume that?+class (HSemiring_ (HIntegral a), HFractional_ a)+    => HContinuous_ (a :: Hakaru)+    where+    type HIntegral (a :: Hakaru) :: Hakaru+    hContinuous :: HContinuous a++instance HContinuous_ 'HProb where+    type HIntegral 'HProb = 'HNat+    hContinuous = HContinuous_Prob++instance HContinuous_ 'HReal where+    type HIntegral 'HReal = 'HInt+    hContinuous = HContinuous_Real+++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/Language/Hakaru/Types/Sing.hs view
@@ -0,0 +1,418 @@+{-# LANGUAGE DataKinds+           , PolyKinds+           , TypeOperators+           , GADTs+           , TypeFamilies+           , FlexibleInstances+           , Rank2Types+           , UndecidableInstances+           #-}++{-# OPTIONS_GHC -Wall -fwarn-tabs #-}+----------------------------------------------------------------+--                                                    2016.05.28+-- |+-- Module      :  Language.Hakaru.Types.Sing+-- Copyright   :  Copyright (c) 2016 the Hakaru team+-- License     :  BSD3+-- Maintainer  :  wren@community.haskell.org+-- Stability   :  experimental+-- Portability :  GHC-only+--+-- Singleton types for the @Hakaru@ kind, and a decision procedure+-- for @Hakaru@ type-equality.+----------------------------------------------------------------+module Language.Hakaru.Types.Sing+    ( Sing(..)+    , SingI(..)+    -- * Some helpful shorthands for \"built-in\" datatypes+    -- ** Constructing singletons+    , sBool+    , sUnit+    , sPair+    , sEither+    , sList+    , sMaybe+    -- ** Destructing singletons+    , sUnMeasure+    , sUnArray+    , sUnPair+    , sUnEither+    , sUnList+    , sUnMaybe+    -- ** Singletons for `Symbol`+    , sSymbol_Bool+    , sSymbol_Unit+    , sSymbol_Pair+    , sSymbol_Either+    , sSymbol_List+    , sSymbol_Maybe+    ) where++import qualified GHC.TypeLits as TL+-- TODO: should we use @(Data.Type.Equality.:~:)@ everywhere instead of our own 'TypeEq'?+import Unsafe.Coerce++import Language.Hakaru.Syntax.IClasses+import Language.Hakaru.Types.DataKind+----------------------------------------------------------------+----------------------------------------------------------------+infixr 0 `SFun`+infixr 6 `SPlus`+infixr 7 `SEt`+++-- | The data families of singletons for each kind.+data family Sing (a :: k) :: *+++-- | A class for automatically generating the singleton for a given+-- Hakaru type.+class SingI (a :: k) where sing :: Sing a++{-+-- TODO: we'd much rather have something like this, to prove that+-- we have a SingI instance for /every/ @a :: Hakaru@. Is there any+-- possible way of actually doing this?++class SingI1 (kproxy :: KProxy k) where+    sing1 :: Sing (a :: k)+    -- or, if it helps at all:+    -- > sing1 :: forall (a :: k). proxy a -> Sing a++instance SingI1 ('KProxy :: KProxy Hakaru) where+    sing1 = undefined+-}++----------------------------------------------------------------+-- BUG: data family instances must be fully saturated, but since+-- these are GADTs, the name of the parameter is irrelevant. However,+-- using a wildcard causes GHC to panic. cf.,+-- <https://ghc.haskell.org/trac/ghc/ticket/10586>++-- | Singleton types for the kind of Hakaru types. We need to use+-- this instead of 'Proxy' in order to implement 'jmEq1'.+data instance Sing (a :: Hakaru) where+    SNat     :: Sing 'HNat+    SInt     :: Sing 'HInt+    SProb    :: Sing 'HProb+    SReal    :: Sing 'HReal+    SMeasure :: !(Sing a) -> Sing ('HMeasure a)+    SArray   :: !(Sing a) -> Sing ('HArray a)+    -- TODO: would it be clearer to use (:$->) in order to better mirror the type-level (:->)+    SFun     :: !(Sing a) -> !(Sing b) -> Sing (a ':-> b)+    SData    :: !(Sing t) -> !(Sing (Code t)) -> Sing (HData' t)+++instance Eq (Sing (a :: Hakaru)) where+    (==) = eq1+instance Eq1 (Sing :: Hakaru -> *) where+    eq1 x y = maybe False (const True) (jmEq1 x y)+instance JmEq1 (Sing :: Hakaru -> *) where+    jmEq1 SNat             SNat             = Just Refl+    jmEq1 SInt             SInt             = Just Refl+    jmEq1 SProb            SProb            = Just Refl+    jmEq1 SReal            SReal            = Just Refl+    jmEq1 (SMeasure a)     (SMeasure b)     =+        jmEq1 a  b  >>= \Refl ->+        Just Refl+    jmEq1 (SArray   a)     (SArray   b)     =+        jmEq1 a  b  >>= \Refl ->+        Just Refl+    jmEq1 (SFun     a1 a2) (SFun     b1 b2) =+        jmEq1 a1 b1 >>= \Refl ->+        jmEq1 a2 b2 >>= \Refl ->+        Just Refl+    jmEq1 (SData con1 code1) (SData con2 code2) =+        jmEq1 con1  con2  >>= \Refl ->+        jmEq1 code1 code2 >>= \Refl ->+        Just Refl+    jmEq1 _ _ = Nothing+++-- TODO: instance Read (Sing (a :: Hakaru))+++instance Show (Sing (a :: Hakaru)) where+    showsPrec = showsPrec1+    show      = show1+instance Show1 (Sing :: Hakaru -> *) where+    showsPrec1 p s =+        case s of+        SNat            -> showString     "SNat"+        SInt            -> showString     "SInt"+        SProb           -> showString     "SProb"+        SReal           -> showString     "SReal"+        SMeasure  s1    -> showParen_1  p "SMeasure"  s1+        SArray    s1    -> showParen_1  p "SArray"    s1+        SFun      s1 s2 -> showParen_11 p "SFun"      s1 s2+        SData     s1 s2 -> showParen_11 p "SData"     s1 s2+++instance SingI 'HNat                            where sing = SNat +instance SingI 'HInt                            where sing = SInt +instance SingI 'HProb                           where sing = SProb +instance SingI 'HReal                           where sing = SReal +instance (SingI a) => SingI ('HMeasure a)       where sing = SMeasure sing+instance (SingI a) => SingI ('HArray a)         where sing = SArray sing+instance (SingI a, SingI b) => SingI (a ':-> b) where sing = SFun sing sing+-- N.B., must use @(~)@ to delay the use of the type family (it's illegal to put it inline in the instance head).+instance (sop ~ Code t, SingI t, SingI sop) => SingI ('HData t sop) where+    sing = SData sing sing+++----------------------------------------------------------------++sUnMeasure :: Sing ('HMeasure a) -> Sing a+sUnMeasure (SMeasure a) = a++sUnArray :: Sing ('HArray a) -> Sing a+sUnArray (SArray a) = a++-- These aren't pattern synonyms (cf., the problems mentioned+-- elsewhere about those), but they're helpful for generating+-- singletons at least.+-- TODO: we might be able to use 'singByProxy' to generate singletons+-- for Symbols? Doesn't work in pattern synonyms, of course.+sUnit :: Sing HUnit+sUnit =+    SData (STyCon sSymbol_Unit)+        (SDone `SPlus` SVoid)++sBool :: Sing HBool+sBool =+    SData (STyCon sSymbol_Bool)+        (SDone `SPlus` SDone `SPlus` SVoid)++-- BUG: what does this "Conflicting definitions for ‘a’" message mean when we try to make this a pattern synonym?+sPair :: Sing a -> Sing b -> Sing (HPair a b)+sPair a b =+    SData (STyCon sSymbol_Pair `STyApp` a `STyApp` b)+        ((SKonst a `SEt` SKonst b `SEt` SDone) `SPlus` SVoid)++sUnPair :: Sing (HPair a b) -> (Sing a, Sing b)+sUnPair (SData (STyApp (STyApp (STyCon _) a) b) _) = (a,b)+sUnPair _ = error "sUnPair: the impossible happened"++sEither :: Sing a -> Sing b -> Sing (HEither a b)+sEither a b =+    SData (STyCon sSymbol_Either `STyApp` a `STyApp` b)+        ((SKonst a `SEt` SDone) `SPlus` (SKonst b `SEt` SDone)+            `SPlus` SVoid)++sUnEither :: Sing (HEither a b) -> (Sing a, Sing b)+sUnEither (SData (STyApp (STyApp (STyCon _) a) b) _) = (a,b)+sUnEither _ = error "sUnEither: the impossible happened"++sList :: Sing a -> Sing (HList a)+sList a =+    SData (STyCon sSymbol_List `STyApp` a)+        (SDone `SPlus` (SKonst a `SEt` SIdent `SEt` SDone) `SPlus` SVoid)++sUnList :: Sing (HList a) -> Sing a+sUnList (SData (STyApp (STyCon _) a) _) = a+sUnList _ = error "sUnList: the impossible happened"++sMaybe :: Sing a -> Sing (HMaybe a)+sMaybe a =+    SData (STyCon sSymbol_Maybe `STyApp` a)+        (SDone `SPlus` (SKonst a `SEt` SDone) `SPlus` SVoid)++sUnMaybe :: Sing (HMaybe a) -> Sing a+sUnMaybe (SData (STyApp (STyCon _) a) _) = a+sUnMaybe _ = error "sUnMaybe: the impossible happened"++----------------------------------------------------------------+data instance Sing (a :: HakaruCon) where+    STyCon :: !(Sing s)              -> Sing ('TyCon s :: HakaruCon)+    STyApp :: !(Sing a) -> !(Sing b) -> Sing (a ':@ b  :: HakaruCon)+++instance Eq (Sing (a :: HakaruCon)) where+    (==) = eq1+instance Eq1 (Sing :: HakaruCon -> *) where+    eq1 x y = maybe False (const True) (jmEq1 x y)+instance JmEq1 (Sing :: HakaruCon -> *) where+    jmEq1 (STyCon s)   (STyCon z)   = jmEq1 s z >>= \Refl -> Just Refl+    jmEq1 (STyApp f a) (STyApp g b) =+        jmEq1 f g >>= \Refl ->+        jmEq1 a b >>= \Refl ->+        Just Refl+    jmEq1 _ _ = Nothing+++-- TODO: instance Read (Sing (a :: HakaruCon))+++instance Show (Sing (a :: HakaruCon)) where+    showsPrec = showsPrec1+    show      = show1+instance Show1 (Sing :: HakaruCon -> *) where+    showsPrec1 p (STyCon s1)    = showParen_1  p "STyCon" s1+    showsPrec1 p (STyApp s1 s2) = showParen_11 p "STyApp" s1 s2+++instance TL.KnownSymbol s => SingI ('TyCon s :: HakaruCon) where+    sing = STyCon sing+instance (SingI a, SingI b) => SingI ((a ':@ b) :: HakaruCon) where+    sing = STyApp sing sing+++----------------------------------------------------------------+-- | N.B., in order to bring the 'TL.KnownSymbol' dictionary into+-- scope, you need to pattern match on the 'SingSymbol' constructor+-- (similar to when we need to match on 'Refl' explicitly). In+-- general you'll want to do this with an at-pattern so that you+-- can also have a variable name for passing the value around (e.g.+-- to be used as an argument to 'TL.symbolVal').+data instance Sing (s :: Symbol) where+    SingSymbol :: TL.KnownSymbol s => Sing (s :: Symbol)++sSymbol_Bool   :: Sing "Bool"+sSymbol_Bool   = SingSymbol+sSymbol_Unit   :: Sing "Unit"+sSymbol_Unit   = SingSymbol+sSymbol_Pair   :: Sing "Pair"+sSymbol_Pair   = SingSymbol+sSymbol_Either :: Sing "Either"+sSymbol_Either = SingSymbol+sSymbol_List   :: Sing "List"+sSymbol_List   = SingSymbol+sSymbol_Maybe  :: Sing "Maybe"+sSymbol_Maybe  = SingSymbol+++instance Eq (Sing (s :: Symbol)) where+    (==) = eq1+instance Eq1 (Sing :: Symbol -> *) where+    eq1 x y = maybe False (const True) (jmEq1 x y)+instance JmEq1 (Sing :: Symbol -> *) where+     jmEq1 x@SingSymbol y@SingSymbol+        | TL.symbolVal x == TL.symbolVal y = Just (unsafeCoerce Refl)+        | otherwise                        = Nothing++-- TODO: is any meaningful Read (Sing (a :: Symbol)) instance possible?++instance Show (Sing (s :: Symbol)) where+    showsPrec = showsPrec1+    show      = show1+instance Show1 (Sing :: Symbol -> *) where+    showsPrec1 _ s@SingSymbol =+        showParen True+            ( showString "SingSymbol :: Sing "+            . showString (show $ TL.symbolVal s)+            )++-- Alas, this requires UndecidableInstances+instance TL.KnownSymbol s => SingI (s :: Symbol) where+    sing = SingSymbol+++----------------------------------------------------------------+data instance Sing (a :: [[HakaruFun]]) where+    SVoid :: Sing ('[] :: [[HakaruFun]])+    SPlus+        :: !(Sing xs)+        -> !(Sing xss)+        -> Sing ((xs ': xss) :: [[HakaruFun]])+++instance Eq (Sing (a :: [[HakaruFun]])) where+    (==) = eq1+instance Eq1 (Sing :: [[HakaruFun]] -> *) where+    eq1 x y = maybe False (const True) (jmEq1 x y)+instance JmEq1 (Sing :: [[HakaruFun]] -> *) where+    jmEq1 SVoid        SVoid        = Just Refl+    jmEq1 (SPlus x xs) (SPlus y ys) =+        jmEq1 x  y  >>= \Refl ->+        jmEq1 xs ys >>= \Refl ->+        Just Refl+    jmEq1 _ _ = Nothing+++-- TODO: instance Read (Sing (a :: [[HakaruFun]]))+++instance Show (Sing (a :: [[HakaruFun]])) where+    showsPrec = showsPrec1+    show      = show1+instance Show1 (Sing :: [[HakaruFun]] -> *) where+    showsPrec1 _ SVoid         = showString     "SVoid"+    showsPrec1 p (SPlus s1 s2) = showParen_11 p "SPlus" s1 s2+++instance SingI ('[] :: [[HakaruFun]]) where+    sing = SVoid+instance (SingI xs, SingI xss) => SingI ((xs ': xss) :: [[HakaruFun]]) where+    sing = SPlus sing sing+++----------------------------------------------------------------+data instance Sing (a :: [HakaruFun]) where+    SDone :: Sing ('[] :: [HakaruFun])+    SEt   :: !(Sing x) -> !(Sing xs) -> Sing ((x ': xs) :: [HakaruFun])+++instance Eq (Sing (a :: [HakaruFun])) where+    (==) = eq1+instance Eq1 (Sing :: [HakaruFun] -> *) where+    eq1 x y = maybe False (const True) (jmEq1 x y)+instance JmEq1 (Sing :: [HakaruFun] -> *) where+    jmEq1 SDone      SDone      = Just Refl+    jmEq1 (SEt x xs) (SEt y ys) =+        jmEq1 x  y  >>= \Refl ->+        jmEq1 xs ys >>= \Refl ->+        Just Refl+    jmEq1 _ _ = Nothing+++-- TODO: instance Read (Sing (a :: [HakaruFun]))+++instance Show (Sing (a :: [HakaruFun])) where+    showsPrec = showsPrec1+    show      = show1+instance Show1 (Sing :: [HakaruFun] -> *) where+    showsPrec1 _ SDone       = showString     "SDone"+    showsPrec1 p (SEt s1 s2) = showParen_11 p "SEt" s1 s2+++instance SingI ('[] :: [HakaruFun]) where+    sing = SDone+instance (SingI x, SingI xs) => SingI ((x ': xs) :: [HakaruFun]) where+    sing = SEt sing sing+++----------------------------------------------------------------+data instance Sing (a :: HakaruFun) where+    SIdent :: Sing 'I+    SKonst :: !(Sing a) -> Sing ('K a)+++instance Eq (Sing (a :: HakaruFun)) where+    (==) = eq1+instance Eq1 (Sing :: HakaruFun -> *) where+    eq1 x y = maybe False (const True) (jmEq1 x y)+instance JmEq1 (Sing :: HakaruFun -> *) where+    jmEq1 SIdent     SIdent     = Just Refl+    jmEq1 (SKonst a) (SKonst b) = jmEq1 a b >>= \Refl -> Just Refl+    jmEq1 _          _          = Nothing+++-- TODO: instance Read (Sing (a :: HakaruFun))+++instance Show (Sing (a :: HakaruFun)) where+    showsPrec = showsPrec1+    show      = show1+instance Show1 (Sing :: HakaruFun -> *) where+    showsPrec1 _ SIdent      = showString    "SIdent"+    showsPrec1 p (SKonst s1) = showParen_1 p "SKonst" s1++instance SingI 'I where+    sing = SIdent+instance (SingI a) => SingI ('K a) where+    sing = SKonst sing++----------------------------------------------------------------+----------------------------------------------------------- fin.
+ haskell/System/MapleSSH.hs view
@@ -0,0 +1,53 @@+module System.MapleSSH (maple) where++import Data.Maybe(fromMaybe)+import Data.Char(isSpace)+import System.IO (hPutStrLn, hClose, hGetContents)+import System.Process (proc, CreateProcess(..), StdStream(CreatePipe), createProcess, waitForProcess)+import System.Environment (lookupEnv)+import System.Exit (ExitCode(ExitSuccess))++-- Default values for SSH environment variables+defSSH, defUser, defServer, defCommand :: String+defSSH     = "/usr/bin/ssh"+defUser    = "ppaml"+defServer  = "karst.uits.iu.edu"+defCommand = "maple"+-- On the server side, ~/.modules should load maple/18, and ~/.mapleinit+-- should point to ~/hakaru/maple (updated by hakaru/maple/MapleUpdate.hs)++envVarsSSH :: IO (String, String, String, String)+envVarsSSH = do+    ssh     <- get "MAPLE_SSH"     defSSH+    user    <- get "MAPLE_USER"    defUser+    server  <- get "MAPLE_SERVER"  defServer+    command <- get "MAPLE_COMMAND" defCommand+    return (ssh, user, server, command)+    where get name def = fmap (fromMaybe def) (lookupEnv name)++process :: IO CreateProcess+process = do+    bin <- lookupEnv "LOCAL_MAPLE"+    case bin of+        Just b  -> return $ proc b ["-q", "-t"]+        Nothing -> +          do (ssh, user, server, command) <- envVarsSSH+             let commands = command ++ " -q -t" -- quiet mode+             return $ proc ssh ["-l" ++ user, server, commands]+++maple :: String -> IO String+maple cmd = do+    p <- process+    (Just inH, Just outH, Nothing, p') <- createProcess p { std_in = CreatePipe, std_out = CreatePipe, close_fds = True }+    hPutStrLn inH $ cmd ++ ";"+    hClose inH+    c <- hGetContents outH+    length c `seq` hClose outH+    exit <- waitForProcess p'+    case exit of+      ExitSuccess -> return $ trim c+      _           -> error ("maple returned exit code: " ++ show exit)++trim :: String -> String+trim = dropWhile isSpace
+ haskell/Tests/TestSuite.hs view
@@ -0,0 +1,40 @@+-- module Tests.TestSuite(main) where++import System.Exit (exitFailure)+import System.Environment (lookupEnv)++import qualified Tests.Parser       as P+import qualified Tests.TypeCheck    as TC+import qualified Tests.Simplify     as S+import qualified Tests.Disintegrate as D+import qualified Tests.Sample       as E+import qualified Tests.RoundTrip    as RT++import Test.HUnit++-- master test suite++ignored :: Assertion+ignored = putStrLn "Warning: maple tests will be ignored"++simplifyTests :: Test -> Maybe String -> Test+simplifyTests t env =+  case env of+    Just _  -> t+    Nothing -> test ignored++allTests :: Maybe String -> Test+allTests env = test+  [ TestLabel "Parser"       P.allTests+  , TestLabel "TypeCheck"    TC.allTests+  , TestLabel "Simplify"     (simplifyTests S.allTests env)+  , TestLabel "Disintegrate" D.allTests+  , TestLabel "Evaluate"     E.allTests+  , TestLabel "RoundTrip"    (simplifyTests RT.allTests env)+  ]++main :: IO ()+main  = do+    env <- lookupEnv "LOCAL_MAPLE"+    Counts _ _ e f <- runTestTT (allTests env)+    if (e>0) || (f>0) then exitFailure else return ()