{-# LANGUAGE TypeFamilies #-}
module Math.HiddenMarkovModel.Public (
   T(..),
   Discrete, DiscreteTrained,
   Gaussian, GaussianTrained,
   uniform,
   generate,
   generateLabeled,
   probabilitySequence,
   Normalized.logLikelihood,
   Normalized.reveal,

   Trained(..),
   trainSupervised,
   Normalized.trainUnsupervised,
   mergeTrained, finishTraining, trainMany,
   deviation,

   toCSV,
   fromCSV,
   ) where

import qualified Math.HiddenMarkovModel.Public.Distribution as Distr
import qualified Math.HiddenMarkovModel.Normalized as Normalized
import qualified Math.HiddenMarkovModel.CSV as HMMCSV
import Math.HiddenMarkovModel.Private
          (T(..), Trained(..), mergeTrained, toCells, parseCSV)
import Math.HiddenMarkovModel.Utility
          (squareConstant, distance, matrixDistance,
           randomItemProp, normalizeProb, attachOnes)

import qualified Numeric.LAPACK.Matrix.Array as ArrMatrix
import qualified Numeric.LAPACK.Matrix as Matrix
import qualified Numeric.LAPACK.Vector as Vector
import Numeric.LAPACK.Matrix ((#!))

import qualified Numeric.Netlib.Class as Class

import qualified Data.Array.Comfort.Storable as StorableArray
import qualified Data.Array.Comfort.Shape as Shape

import qualified Text.CSV.Lazy.String as CSV

import qualified System.Random as Rnd

import qualified Control.Monad.Exception.Synchronous as ME
import qualified Control.Monad.Trans.State as MS
import qualified Control.Monad.HT as Monad

import qualified Data.NonEmpty as NonEmpty
import Data.Traversable (Traversable, mapAccumL)
import Data.Foldable (Foldable)



type DiscreteTrained symbol sh prob =
         Trained (Distr.Discrete symbol) sh prob
type Discrete symbol sh prob = T (Distr.Discrete symbol) sh prob

type GaussianTrained emiSh stateSh a =
         Trained (Distr.Gaussian emiSh) stateSh a
type Gaussian emiSh stateSh a = T (Distr.Gaussian emiSh) stateSh a


{- |
Create a model with uniform probabilities
for initial vector and transition matrix
given a distribution for the emissions.
You can use this as a starting point for 'Normalized.trainUnsupervised'.
-}
uniform ::
   (Distr.Info typ, Shape.C sh, Class.Real prob) =>
   Distr.T typ sh prob -> T typ sh prob
uniform :: T typ sh prob -> T typ sh prob
uniform T typ sh prob
distr =
   let sh :: sh
sh = T typ sh prob -> sh
forall typ sh prob. (Info typ, C sh) => T typ sh prob -> sh
Distr.statesShape T typ sh prob
distr
       c :: prob
c = prob -> prob
forall a. Fractional a => a -> a
recip (prob -> prob) -> prob -> prob
forall a b. (a -> b) -> a -> b
$ Int -> prob
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> prob) -> Int -> prob
forall a b. (a -> b) -> a -> b
$ sh -> Int
forall sh. C sh => sh -> Int
Shape.size sh
sh
   in  Cons :: forall typ sh prob.
Vector sh prob -> Square sh prob -> T typ sh prob -> T typ sh prob
Cons {
          initial :: Vector sh prob
initial = sh -> prob -> Vector sh prob
forall sh a. (C sh, Floating a) => sh -> a -> Vector sh a
Vector.constant sh
sh prob
c,
          transition :: Square sh prob
transition = sh -> prob -> Square sh prob
forall sh a. (C sh, Real a) => sh -> a -> Square sh a
squareConstant sh
sh prob
c,
          distribution :: T typ sh prob
distribution = T typ sh prob
distr
       }


probabilitySequence ::
   (Distr.EmissionProb typ, Shape.Indexed sh, Shape.Index sh ~ state,
    Class.Real prob, Distr.Emission typ prob ~ emission, Traversable f) =>
   T typ sh prob -> f (state, emission) -> f prob
probabilitySequence :: T typ sh prob -> f (state, emission) -> f prob
probabilitySequence T typ sh prob
hmm =
   (state -> prob, f prob) -> f prob
forall a b. (a, b) -> b
snd
   ((state -> prob, f prob) -> f prob)
-> (f (state, emission) -> (state -> prob, f prob))
-> f (state, emission)
-> f prob
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
   ((state -> prob) -> (state, emission) -> (state -> prob, prob))
-> (state -> prob)
-> f (state, emission)
-> (state -> prob, f prob)
forall (t :: * -> *) a b c.
Traversable t =>
(a -> b -> (a, c)) -> a -> t b -> (a, t c)
mapAccumL
      (\state -> prob
index (state
s, emission
e) ->
         ((T typ sh prob -> Square sh prob
forall typ sh prob. T typ sh prob -> Square sh prob
transition T typ sh prob
hmm Square sh prob -> (Index sh, Index sh) -> prob
forall typ meas vert horiz height width a xl xu lower upper.
(Indexed typ, Measure meas, C vert, C horiz, Indexed height,
 Indexed width, Floating a) =>
Matrix typ xl xu lower upper meas vert horiz height width a
-> (Index height, Index width) -> a
#!) ((state, state) -> prob)
-> (state -> (state, state)) -> state -> prob
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (state -> state -> (state, state))
-> state -> state -> (state, state)
forall a b c. (a -> b -> c) -> b -> a -> c
flip (,) state
s,
          state -> prob
index state
s prob -> prob -> prob
forall a. Num a => a -> a -> a
* T typ sh prob -> Emission typ prob -> Index sh -> prob
forall typ sh prob.
(EmissionProb typ, Indexed sh, Real prob) =>
T typ sh prob -> Emission typ prob -> Index sh -> prob
Distr.emissionStateProb (T typ sh prob -> T typ sh prob
forall typ sh prob. T typ sh prob -> T typ sh prob
distribution T typ sh prob
hmm) emission
Emission typ prob
e state
Index sh
s))
      (T typ sh prob -> Vector sh prob
forall typ sh prob. T typ sh prob -> Vector sh prob
initial T typ sh prob
hmm Vector sh prob -> Index sh -> prob
forall sh a.
(Indexed sh, Storable a) =>
Array sh a -> Index sh -> a
StorableArray.!)

generate ::
   (Distr.Generate typ, Shape.Indexed sh, Class.Real prob,
    Rnd.RandomGen g, Rnd.Random prob, Distr.Emission typ prob ~ emission) =>
   T typ sh prob -> g -> [emission]
generate :: T typ sh prob -> g -> [emission]
generate T typ sh prob
hmm = ((Index sh, emission) -> emission)
-> [(Index sh, emission)] -> [emission]
forall a b. (a -> b) -> [a] -> [b]
map (Index sh, emission) -> emission
forall a b. (a, b) -> b
snd ([(Index sh, emission)] -> [emission])
-> (g -> [(Index sh, emission)]) -> g -> [emission]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. T typ sh prob -> g -> [(Index sh, emission)]
forall typ sh state g prob emission.
(Generate typ, Indexed sh, Index sh ~ state, RandomGen g,
 Random prob, Real prob, Emission typ prob ~ emission) =>
T typ sh prob -> g -> [(state, emission)]
generateLabeled T typ sh prob
hmm

generateLabeled ::
   (Distr.Generate typ, Shape.Indexed sh, Shape.Index sh ~ state,
    Rnd.RandomGen g, Rnd.Random prob,
    Class.Real prob, Distr.Emission typ prob ~ emission) =>
   T typ sh prob -> g -> [(state, emission)]
generateLabeled :: T typ sh prob -> g -> [(state, emission)]
generateLabeled T typ sh prob
hmm =
   State g [(state, emission)] -> g -> [(state, emission)]
forall s a. State s a -> s -> a
MS.evalState (State g [(state, emission)] -> g -> [(state, emission)])
-> State g [(state, emission)] -> g -> [(state, emission)]
forall a b. (a -> b) -> a -> b
$
   (StateT (Vector sh prob) (StateT g Identity) [(state, emission)]
 -> Vector sh prob -> State g [(state, emission)])
-> Vector sh prob
-> StateT (Vector sh prob) (StateT g Identity) [(state, emission)]
-> State g [(state, emission)]
forall a b c. (a -> b -> c) -> b -> a -> c
flip StateT (Vector sh prob) (StateT g Identity) [(state, emission)]
-> Vector sh prob -> State g [(state, emission)]
forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
MS.evalStateT (T typ sh prob -> Vector sh prob
forall typ sh prob. T typ sh prob -> Vector sh prob
initial T typ sh prob
hmm) (StateT (Vector sh prob) (StateT g Identity) [(state, emission)]
 -> State g [(state, emission)])
-> StateT (Vector sh prob) (StateT g Identity) [(state, emission)]
-> State g [(state, emission)]
forall a b. (a -> b) -> a -> b
$
   StateT (Vector sh prob) (StateT g Identity) (state, emission)
-> StateT (Vector sh prob) (StateT g Identity) [(state, emission)]
forall (m :: * -> *) a. Monad m => m a -> m [a]
Monad.repeat (StateT (Vector sh prob) (StateT g Identity) (state, emission)
 -> StateT (Vector sh prob) (StateT g Identity) [(state, emission)])
-> StateT (Vector sh prob) (StateT g Identity) (state, emission)
-> StateT (Vector sh prob) (StateT g Identity) [(state, emission)]
forall a b. (a -> b) -> a -> b
$ (Vector sh prob
 -> StateT g Identity ((state, emission), Vector sh prob))
-> StateT (Vector sh prob) (StateT g Identity) (state, emission)
forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
MS.StateT ((Vector sh prob
  -> StateT g Identity ((state, emission), Vector sh prob))
 -> StateT (Vector sh prob) (StateT g Identity) (state, emission))
-> (Vector sh prob
    -> StateT g Identity ((state, emission), Vector sh prob))
-> StateT (Vector sh prob) (StateT g Identity) (state, emission)
forall a b. (a -> b) -> a -> b
$ \Vector sh prob
v0 -> do
      state
s <-
         [(state, prob)] -> State g state
forall g b a.
(RandomGen g, Random b, Num b, Ord b) =>
[(a, b)] -> State g a
randomItemProp ([(state, prob)] -> State g state)
-> [(state, prob)] -> State g state
forall a b. (a -> b) -> a -> b
$
         [state] -> [prob] -> [(state, prob)]
forall a b. [a] -> [b] -> [(a, b)]
zip (sh -> [Index sh]
forall sh. Indexed sh => sh -> [Index sh]
Shape.indices (sh -> [Index sh]) -> sh -> [Index sh]
forall a b. (a -> b) -> a -> b
$ Vector sh prob -> sh
forall sh a. Array sh a -> sh
StorableArray.shape Vector sh prob
v0) (Vector sh prob -> [prob]
forall sh a. (C sh, Storable a) => Vector sh a -> [a]
Vector.toList Vector sh prob
v0)
      emission
x <- T typ sh prob -> Index sh -> State g (Emission typ prob)
forall typ sh prob g.
(Generate typ, Indexed sh, Real prob, Random prob, RandomGen g) =>
T typ sh prob -> Index sh -> State g (Emission typ prob)
Distr.generate (T typ sh prob -> T typ sh prob
forall typ sh prob. T typ sh prob -> T typ sh prob
distribution T typ sh prob
hmm) state
Index sh
s
      ((state, emission), Vector sh prob)
-> StateT g Identity ((state, emission), Vector sh prob)
forall (m :: * -> *) a. Monad m => a -> m a
return ((state
s, emission
x), Full Shape Small Small sh sh prob -> state -> Vector sh prob
forall meas vert horiz height width ix a.
(Measure meas, C vert, C horiz, C height, Indexed width,
 Index width ~ ix, Floating a) =>
Full meas vert horiz height width a -> ix -> Vector height a
Matrix.takeColumn (T typ sh prob -> Full Shape Small Small sh sh prob
forall typ sh prob. T typ sh prob -> Square sh prob
transition T typ sh prob
hmm) state
s)



{- |
Contribute a manually labeled emission sequence to a HMM training.
-}
trainSupervised ::
   (Distr.Estimate typ, Shape.Indexed sh, Shape.Index sh ~ state,
    Class.Real prob, Distr.Emission typ prob ~ emission) =>
   sh -> NonEmpty.T [] (state, emission) -> Trained typ sh prob
trainSupervised :: sh -> T [] (state, emission) -> Trained typ sh prob
trainSupervised sh
sh T [] (state, emission)
xs =
   let getState :: (a, b) -> a
getState (a
s, b
_x) = a
s
   in  Trained :: forall typ sh prob.
Vector sh prob
-> Square sh prob -> Trained typ sh prob -> Trained typ sh prob
Trained {
          trainedInitial :: Vector sh prob
trainedInitial = sh -> Index sh -> Vector sh prob
forall sh a.
(Indexed sh, Floating a) =>
sh -> Index sh -> Vector sh a
Vector.unit sh
sh (Index sh -> Vector sh prob) -> Index sh -> Vector sh prob
forall a b. (a -> b) -> a -> b
$ (state, emission) -> state
forall a b. (a, b) -> a
getState ((state, emission) -> state) -> (state, emission) -> state
forall a b. (a -> b) -> a -> b
$ T [] (state, emission) -> (state, emission)
forall (f :: * -> *) a. T f a -> a
NonEmpty.head T [] (state, emission)
xs,
          trainedTransition :: Square sh prob
trainedTransition =
             Square sh prob -> Square sh prob
forall typ meas vert horiz width height a xl xu lower upper.
(Transpose typ, Measure meas, C vert, C horiz, C width, C height,
 Floating a) =>
Matrix typ xl xu lower upper meas vert horiz height width a
-> Matrix typ xu xl upper lower meas horiz vert width height a
Matrix.transpose (Square sh prob -> Square sh prob)
-> Square sh prob -> Square sh prob
forall a b. (a -> b) -> a -> b
$ Array (Full Shape Small Small sh sh) prob -> Square sh prob
forall pack prop lower upper meas vert horiz height width shape a.
(FromPlain pack prop lower upper meas vert horiz height width,
 Plain pack prop lower upper meas vert horiz height width ~ shape,
 Measure meas, C vert, C horiz, C height, C width, Floating a) =>
Array shape a
-> ArrayMatrix pack prop lower upper meas vert horiz height width a
ArrMatrix.fromVector (Array (Full Shape Small Small sh sh) prob -> Square sh prob)
-> Array (Full Shape Small Small sh sh) prob -> Square sh prob
forall a b. (a -> b) -> a -> b
$
             (prob -> prob -> prob)
-> Array (Full Shape Small Small sh sh) prob
-> [(Index (Full Shape Small Small sh sh), prob)]
-> Array (Full Shape Small Small sh sh) prob
forall sh a b.
(Indexed sh, Storable a) =>
(a -> b -> a) -> Array sh a -> [(Index sh, b)] -> Array sh a
StorableArray.accumulate prob -> prob -> prob
forall a. Num a => a -> a -> a
(+)
                (Square sh prob
-> PlainArray
     Unpacked Arbitrary Filled Filled Shape Small Small sh sh prob
forall pack property lower upper meas vert horiz height width a.
ToPlain pack property lower upper meas vert horiz height width =>
ArrayMatrix
  pack property lower upper meas vert horiz height width a
-> PlainArray
     pack property lower upper meas vert horiz height width a
ArrMatrix.toVector (Square sh prob
 -> PlainArray
      Unpacked Arbitrary Filled Filled Shape Small Small sh sh prob)
-> Square sh prob
-> PlainArray
     Unpacked Arbitrary Filled Filled Shape Small Small sh sh prob
forall a b. (a -> b) -> a -> b
$ sh -> prob -> Square sh prob
forall sh a. (C sh, Real a) => sh -> a -> Square sh a
squareConstant sh
sh prob
0) ([(Index (Full Shape Small Small sh sh), prob)]
 -> Array (Full Shape Small Small sh sh) prob)
-> [(Index (Full Shape Small Small sh sh), prob)]
-> Array (Full Shape Small Small sh sh) prob
forall a b. (a -> b) -> a -> b
$
             [(state, state)] -> [((state, state), prob)]
forall b a. Num b => [a] -> [(a, b)]
attachOnes ([(state, state)] -> [((state, state), prob)])
-> [(state, state)] -> [((state, state), prob)]
forall a b. (a -> b) -> a -> b
$ (state -> state -> (state, state))
-> T [] state -> [(state, state)]
forall (f :: * -> *) a b.
Traversable f =>
(a -> a -> b) -> T f a -> f b
NonEmpty.mapAdjacent (,) (T [] state -> [(state, state)]) -> T [] state -> [(state, state)]
forall a b. (a -> b) -> a -> b
$ ((state, emission) -> state)
-> T [] (state, emission) -> T [] state
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (state, emission) -> state
forall a b. (a, b) -> a
getState T [] (state, emission)
xs,
          trainedDistribution :: Trained typ sh prob
trainedDistribution = sh -> T [] (state, Emission typ prob) -> Trained typ sh prob
forall typ sh prob state.
(Estimate typ, Indexed sh, Real prob, Index sh ~ state) =>
sh -> T [] (state, Emission typ prob) -> Trained typ sh prob
Distr.accumulateEmissions sh
sh T [] (state, emission)
T [] (state, Emission typ prob)
xs
       }

finishTraining ::
   (Distr.Estimate typ, Shape.C sh, Eq sh, Class.Real prob) =>
   Trained typ sh prob -> T typ sh prob
finishTraining :: Trained typ sh prob -> T typ sh prob
finishTraining Trained typ sh prob
hmm =
   Cons :: forall typ sh prob.
Vector sh prob -> Square sh prob -> T typ sh prob -> T typ sh prob
Cons {
      initial :: Vector sh prob
initial = Vector sh prob -> Vector sh prob
forall sh a. (C sh, Real a) => Vector sh a -> Vector sh a
normalizeProb (Vector sh prob -> Vector sh prob)
-> Vector sh prob -> Vector sh prob
forall a b. (a -> b) -> a -> b
$ Trained typ sh prob -> Vector sh prob
forall typ sh prob. Trained typ sh prob -> Vector sh prob
trainedInitial Trained typ sh prob
hmm,
      transition :: Square sh prob
transition = Square sh prob -> Square sh prob
forall sh a. (C sh, Eq sh, Real a) => Square sh a -> Square sh a
normalizeProbColumns (Square sh prob -> Square sh prob)
-> Square sh prob -> Square sh prob
forall a b. (a -> b) -> a -> b
$ Trained typ sh prob -> Square sh prob
forall typ sh prob. Trained typ sh prob -> Square sh prob
trainedTransition Trained typ sh prob
hmm,
      distribution :: T typ sh prob
distribution = Trained typ sh prob -> T typ sh prob
forall typ sh prob.
(Estimate typ, C sh, Eq sh, Real prob) =>
Trained typ sh prob -> T typ sh prob
Distr.normalize (Trained typ sh prob -> T typ sh prob)
-> Trained typ sh prob -> T typ sh prob
forall a b. (a -> b) -> a -> b
$ Trained typ sh prob -> Trained typ sh prob
forall typ sh prob. Trained typ sh prob -> Trained typ sh prob
trainedDistribution Trained typ sh prob
hmm
   }

normalizeProbColumns ::
   (Shape.C sh, Eq sh, Class.Real a) => Matrix.Square sh a -> Matrix.Square sh a
normalizeProbColumns :: Square sh a -> Square sh a
normalizeProbColumns Square sh a
m =
   Vector sh a -> Square sh a -> Square sh a
forall meas vert horiz height width a.
(Measure meas, C vert, C horiz, C height, C width, Eq width,
 Floating a) =>
Vector width a
-> Full meas vert horiz height width a
-> Full meas vert horiz height width a
Matrix.scaleColumns ((a -> a) -> Vector sh a -> Vector sh a
forall sh a b.
(C sh, Storable a, Storable b) =>
(a -> b) -> Array sh a -> Array sh b
StorableArray.map a -> a
forall a. Fractional a => a -> a
recip (Square sh a -> Vector sh a
forall meas vert horiz height width a.
(Measure meas, C vert, C horiz, C height, C width, Floating a) =>
Full meas vert horiz height width a -> Vector width a
Matrix.columnSums Square sh a
m)) Square sh a
m

trainMany ::
   (Distr.Estimate typ, Shape.C sh, Eq sh, Class.Real prob, Foldable f) =>
   (trainingData -> Trained typ sh prob) ->
   NonEmpty.T f trainingData -> T typ sh prob
trainMany :: (trainingData -> Trained typ sh prob)
-> T f trainingData -> T typ sh prob
trainMany trainingData -> Trained typ sh prob
train = Trained typ sh prob -> T typ sh prob
forall typ sh prob.
(Estimate typ, C sh, Eq sh, Real prob) =>
Trained typ sh prob -> T typ sh prob
finishTraining (Trained typ sh prob -> T typ sh prob)
-> (T f trainingData -> Trained typ sh prob)
-> T f trainingData
-> T typ sh prob
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Trained typ sh prob -> Trained typ sh prob -> Trained typ sh prob)
-> (trainingData -> Trained typ sh prob)
-> T f trainingData
-> Trained typ sh prob
forall (f :: * -> *) b a.
Foldable f =>
(b -> b -> b) -> (a -> b) -> T f a -> b
NonEmpty.foldl1Map Trained typ sh prob -> Trained typ sh prob -> Trained typ sh prob
forall typ sh prob.
(Estimate typ, C sh, Eq sh, Real prob) =>
Trained typ sh prob -> Trained typ sh prob -> Trained typ sh prob
mergeTrained trainingData -> Trained typ sh prob
train





{- |
Compute maximum deviation between initial and transition probabilities.
You can use this as abort criterion for unsupervised training.
We omit computation of differences between the emission probabilities.
This simplifies matters a lot and
should suffice for defining an abort criterion.
-}
deviation ::
   (Shape.C sh, Eq sh, Class.Real prob) =>
   T typ sh prob -> T typ sh prob -> prob
deviation :: T typ sh prob -> T typ sh prob -> prob
deviation T typ sh prob
hmm0 T typ sh prob
hmm1 =
   Vector sh prob -> Vector sh prob -> prob
forall sh a.
(C sh, Eq sh, Real a) =>
Vector sh a -> Vector sh a -> a
distance (T typ sh prob -> Vector sh prob
forall typ sh prob. T typ sh prob -> Vector sh prob
initial T typ sh prob
hmm0) (T typ sh prob -> Vector sh prob
forall typ sh prob. T typ sh prob -> Vector sh prob
initial T typ sh prob
hmm1)
   prob -> prob -> prob
forall a. Ord a => a -> a -> a
`max`
   ArrayMatrix
  Unpacked Arbitrary Filled Filled Shape Small Small sh sh prob
-> ArrayMatrix
     Unpacked Arbitrary Filled Filled Shape Small Small sh sh prob
-> prob
forall meas vert horiz height width a pack prop lower upper.
(Measure meas, C vert, C horiz, C height, C width, Eq height,
 Eq width, Real a) =>
ArrayMatrix pack prop lower upper meas vert horiz height width a
-> ArrayMatrix pack prop lower upper meas vert horiz height width a
-> a
matrixDistance (T typ sh prob
-> ArrayMatrix
     Unpacked Arbitrary Filled Filled Shape Small Small sh sh prob
forall typ sh prob. T typ sh prob -> Square sh prob
transition T typ sh prob
hmm0) (T typ sh prob
-> ArrayMatrix
     Unpacked Arbitrary Filled Filled Shape Small Small sh sh prob
forall typ sh prob. T typ sh prob -> Square sh prob
transition T typ sh prob
hmm1)


toCSV ::
   (Distr.ToCSV typ, Shape.Indexed sh, Class.Real prob, Show prob) =>
   T typ sh prob -> String
toCSV :: T typ sh prob -> String
toCSV T typ sh prob
hmm =
   CSVTable -> String
CSV.ppCSVTable (CSVTable -> String) -> CSVTable -> String
forall a b. (a -> b) -> a -> b
$ ([CSVError], CSVTable) -> CSVTable
forall a b. (a, b) -> b
snd (([CSVError], CSVTable) -> CSVTable)
-> ([CSVError], CSVTable) -> CSVTable
forall a b. (a -> b) -> a -> b
$ [[String]] -> ([CSVError], CSVTable)
CSV.toCSVTable ([[String]] -> ([CSVError], CSVTable))
-> [[String]] -> ([CSVError], CSVTable)
forall a b. (a -> b) -> a -> b
$ String -> [[String]] -> [[String]]
forall a. a -> [[a]] -> [[a]]
HMMCSV.padTable String
"" ([[String]] -> [[String]]) -> [[String]] -> [[String]]
forall a b. (a -> b) -> a -> b
$ T typ sh prob -> [[String]]
forall typ sh prob.
(ToCSV typ, Indexed sh, Real prob, Show prob) =>
T typ sh prob -> [[String]]
toCells T typ sh prob
hmm

fromCSV ::
   (Distr.FromCSV typ, Shape.Indexed sh, Eq sh, Class.Real prob, Read prob) =>
   (Int -> sh) -> String -> ME.Exceptional String (T typ sh prob)
fromCSV :: (Int -> sh) -> String -> Exceptional String (T typ sh prob)
fromCSV Int -> sh
makeShape =
   StateT CSVResult (Exceptional String) (T typ sh prob)
-> CSVResult -> Exceptional String (T typ sh prob)
forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
MS.evalStateT ((Int -> sh)
-> StateT CSVResult (Exceptional String) (T typ sh prob)
forall typ stateSh prob.
(FromCSV typ, C stateSh, Eq stateSh, Real prob, Read prob) =>
(Int -> stateSh) -> CSVParser (T typ stateSh prob)
parseCSV Int -> sh
makeShape) (CSVResult -> Exceptional String (T typ sh prob))
-> (String -> CSVResult)
-> String
-> Exceptional String (T typ sh prob)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Either [CSVError] CSVRow -> Either [CSVError] CSVRow)
-> CSVResult -> CSVResult
forall a b. (a -> b) -> [a] -> [b]
map Either [CSVError] CSVRow -> Either [CSVError] CSVRow
HMMCSV.fixShortRow (CSVResult -> CSVResult)
-> (String -> CSVResult) -> String -> CSVResult
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> CSVResult
CSV.parseCSV