diff --git a/Changes.md b/Changes.md
new file mode 100644
--- /dev/null
+++ b/Changes.md
@@ -0,0 +1,3 @@
+## 0.1
+
+* `Distribution.Estimate` turned into a multi-parameter type class.
diff --git a/hmm-hmatrix.cabal b/hmm-hmatrix.cabal
--- a/hmm-hmatrix.cabal
+++ b/hmm-hmatrix.cabal
@@ -1,5 +1,5 @@
 Name:                hmm-hmatrix
-Version:             0.0.2
+Version:             0.1
 Synopsis:            Hidden Markov Models using HMatrix primitives
 Description:
   Hidden Markov Models implemented using HMatrix data types and operations.
@@ -37,9 +37,11 @@
 Category:            Math
 Build-Type:          Simple
 Cabal-Version:       >=1.10
+Extra-Source-Files:
+  Changes.md
 
 Source-Repository this
-  Tag:         0.0.2
+  Tag:         0.1
   Type:        darcs
   Location:    http://hub.darcs.net/thielema/hmm-hmatrix
 
diff --git a/src/Math/HiddenMarkovModel.hs b/src/Math/HiddenMarkovModel.hs
--- a/src/Math/HiddenMarkovModel.hs
+++ b/src/Math/HiddenMarkovModel.hs
@@ -116,8 +116,7 @@
 Contribute a manually labeled emission sequence to a HMM training.
 -}
 trainSupervised ::
-   (Distr.Estimate tdistr, Distr.Distribution tdistr ~ distr,
-    Distr.Trained distr ~ tdistr,
+   (Distr.Estimate tdistr distr,
     Distr.Probability distr ~ prob, Distr.Emission distr ~ emission) =>
    Int -> NonEmpty.T [] (State, emission) -> Trained tdistr prob
 trainSupervised n xs =
@@ -133,8 +132,7 @@
        }
 
 finishTraining ::
-   (Distr.Estimate tdistr, Distr.Distribution tdistr ~ distr,
-    Distr.Trained distr ~ tdistr, Distr.Probability distr ~ prob) =>
+   (Distr.Estimate tdistr distr, Distr.Probability distr ~ prob) =>
    Trained tdistr prob -> T distr prob
 finishTraining hmm =
    Cons {
@@ -146,8 +144,7 @@
    }
 
 trainMany ::
-   (Distr.Estimate tdistr, Distr.Distribution tdistr ~ distr,
-    Distr.Trained distr ~ tdistr, Distr.Probability distr ~ prob,
+   (Distr.Estimate tdistr distr, Distr.Probability distr ~ prob,
     Foldable f) =>
    (trainingData -> Trained tdistr prob) ->
    NonEmpty.T f trainingData -> T distr prob
diff --git a/src/Math/HiddenMarkovModel/Distribution.hs b/src/Math/HiddenMarkovModel/Distribution.hs
--- a/src/Math/HiddenMarkovModel/Distribution.hs
+++ b/src/Math/HiddenMarkovModel/Distribution.hs
@@ -1,8 +1,9 @@
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
 module Math.HiddenMarkovModel.Distribution (
    State(..),
-   Emission, Probability, Trained,
+   Emission, Probability,
    Info(..), Generate(..), EmissionProb(..), Estimate(..),
 
    Discrete(..), DiscreteTrained(..),
@@ -62,7 +63,6 @@
 
 type family Probability distr
 type family Emission distr
-type family Trained distr
 
 
 class
@@ -89,16 +89,15 @@
    emissionStateProb distr e (State s) = NC.atIndex (emissionProb distr e) s
 
 class
-   (EmissionProb (Distribution tdistr),
-    Trained (Distribution tdistr) ~ tdistr) =>
-      Estimate tdistr where
+   (Distribution tdistr ~ distr, Trained distr ~ tdistr, EmissionProb distr) =>
+      Estimate tdistr distr where
    type Distribution tdistr
+   type Trained distr
    accumulateEmissions ::
-      (Distribution tdistr ~ distr, Probability distr ~ prob) =>
-      [[(Emission distr, prob)]] -> tdistr
+      (Probability distr ~ prob) => [[(Emission distr, prob)]] -> tdistr
    -- could as well be in Semigroup class
    combine :: tdistr -> tdistr -> tdistr
-   normalize :: (Distribution tdistr ~ distr) => tdistr -> distr
+   normalize :: tdistr -> distr
 
 
 
@@ -111,9 +110,7 @@
 type instance Probability (Discrete prob symbol) = prob
 type instance Emission (Discrete prob symbol) = symbol
 
-type instance Trained (Discrete prob symbol) = DiscreteTrained prob symbol
 
-
 instance (NFData prob, NFData symbol) => NFData (Discrete prob symbol) where
    rnf (Discrete m) = rnf m
 
@@ -142,8 +139,9 @@
 
 instance
    (NC.Container Vector prob, NC.Product prob, Ord symbol) =>
-      Estimate (DiscreteTrained prob symbol) where
+      Estimate (DiscreteTrained prob symbol) (Discrete prob symbol) where
    type Distribution (DiscreteTrained prob symbol) = Discrete prob symbol
+   type Trained (Discrete prob symbol) = DiscreteTrained prob symbol
    accumulateEmissions grouped =
       let set = Set.toAscList $ foldMap (Set.fromList . map fst) grouped
           emi = Map.fromAscList $ zip set [0..]
@@ -178,9 +176,7 @@
 type instance Probability (Gaussian a) = a
 type instance Emission (Gaussian a) = Vector a
 
-type instance Trained (Gaussian a) = GaussianTrained a
 
-
 instance (NFData a, Storable a) => NFData (Gaussian a) where
    rnf (Gaussian params) = rnf params
 
@@ -216,8 +212,11 @@
          in  c * exp ((-1/2) * NC.dot x0 (cholSolve covarianceChol x0))
 
 
-instance (HMatrix.Numeric a, Algo.Field a) => Estimate (GaussianTrained a) where
+instance
+   (HMatrix.Numeric a, Algo.Field a) =>
+      Estimate (GaussianTrained a) (Gaussian a) where
    type Distribution (GaussianTrained a) = Gaussian a
+   type Trained (Gaussian a) = GaussianTrained a
    accumulateEmissions =
       let params xs =
              let center =
diff --git a/src/Math/HiddenMarkovModel/Normalized.hs b/src/Math/HiddenMarkovModel/Normalized.hs
--- a/src/Math/HiddenMarkovModel/Normalized.hs
+++ b/src/Math/HiddenMarkovModel/Normalized.hs
@@ -151,8 +151,7 @@
 This is done by the Baum-Welch algorithm.
 -}
 trainUnsupervised ::
-   (Distr.Estimate tdistr, Distr.Distribution tdistr ~ distr,
-    Distr.Trained distr ~ tdistr,
+   (Distr.Estimate tdistr distr,
     Distr.Probability distr ~ prob, Distr.Emission distr ~ emission) =>
    T distr prob -> NonEmpty.T [] emission -> Trained tdistr prob
 trainUnsupervised hmm xs =
diff --git a/src/Math/HiddenMarkovModel/Private.hs b/src/Math/HiddenMarkovModel/Private.hs
--- a/src/Math/HiddenMarkovModel/Private.hs
+++ b/src/Math/HiddenMarkovModel/Private.hs
@@ -231,14 +231,12 @@
    T distr e -> [Matrix e] -> Matrix e
 sumTransitions hmm =
    List.foldl' NC.add (NC.konst 0 $ LinAlg.size $ transition hmm)
---    zero = uncurry LinAlg.zeros $ LinAlg.size $ transition hmm
 
 {- |
 Baum-Welch algorithm
 -}
 trainUnsupervised ::
-   (Distr.Estimate tdistr, Distr.Distribution tdistr ~ distr,
-    Distr.Trained distr ~ tdistr,
+   (Distr.Estimate tdistr distr,
     Distr.Probability distr ~ prob, Distr.Emission distr ~ emission) =>
    T distr prob -> NonEmpty.T [] emission -> Trained tdistr prob
 trainUnsupervised hmm xs =
@@ -257,8 +255,7 @@
 
 
 mergeTrained ::
-   (Distr.Estimate tdistr, Distr.Distribution tdistr ~ distr,
-    Distr.Trained distr ~ tdistr, Distr.Probability distr ~ prob) =>
+   (Distr.Estimate tdistr distr, Distr.Probability distr ~ prob) =>
    Trained tdistr prob -> Trained tdistr prob -> Trained tdistr prob
 mergeTrained hmm0 hmm1 =
    Trained {
@@ -271,8 +268,7 @@
    }
 
 instance
-   (Distr.Estimate tdistr, Distr.Distribution tdistr ~ distr,
-    Distr.Probability distr ~ prob) =>
+   (Distr.Estimate tdistr distr, Distr.Probability distr ~ prob) =>
       Sg.Semigroup (Trained tdistr prob) where
    (<>) = mergeTrained
 
