title: How can I improve my understanding of the Haskell Type system?
body: <p>After a lot of tinkering at a random number generator, I have come to the conclusion that my understanding of the Haskell type system is incomplete, if not missing altogether.</p>
  
  <p>Here's an example. I'm trying to generate a stream of Poisson event times:</p>
  
  <pre><code>import System.Random
  import Numeric
  
  bround :: (RealFloat r, Integral b) =&gt; b -&gt; r -&gt; r
  bround places x = (fromIntegral (round ( x * exp))) / exp
         where exp = 10.0 ^ places
  
  rndp = (bround 4)
  
  myGen = (mkStdGen 1278267)
  
  infinitePoissonStream :: (RandomGen g, Random r, RealFloat r) =&gt; r -&gt; r -&gt; g -&gt; [r]
  infinitePoissonStream rate start gen = next:(infinitePoissonStream rate next newGen)
          where  (rvalue, newGen) = random gen
                 next = (start - log(rvalue) / rate)
  
  printAll :: (RealFloat r) =&gt; [r] -&gt; IO ()
  printAll []     = return ()
  printAll (x:xs) = do putStrLn (showFFloat (Just 8) x "")
                       printAll xs
  
  main = do
         printAll (take 10 (infinitePoissonStream 1.0 0.0 myGen ) )
  </code></pre>
  
  <p>which chides me thus:</p>
  
  <pre><code>mwe3.hs:23:8:
      No instance for (RealFloat r0) arising from a use of `printAll'
      The type variable `r0' is ambiguous
      Possible fix: add a type signature that fixes these type variable(s)
      Note: there are several potential instances:
        instance RealFloat Double -- Defined in `GHC.Float'
        instance RealFloat Float -- Defined in `GHC.Float'
        instance RealFloat Foreign.C.Types.CDouble
          -- Defined in `Foreign.C.Types'
        ...plus one other
      In a stmt of a 'do' block:
        printAll (take 10 (infinitePoissonStream 1.0 0.0 myGen))
      In the expression:
        do { printAll (take 10 (infinitePoissonStream 1.0 0.0 myGen)) }
      In an equation for `main':
          main
            = do { printAll (take 10 (infinitePoissonStream 1.0 0.0 myGen)) }
  
  mwe3.hs:23:27:
      No instance for (Random r0)
        arising from a use of `infinitePoissonStream'
      The type variable `r0' is ambiguous
      Possible fix: add a type signature that fixes these type variable(s)
      Note: there are several potential instances:
        instance Random Bool -- Defined in `System.Random'
        instance Random Foreign.C.Types.CChar -- Defined in `System.Random'
        instance Random Foreign.C.Types.CDouble
          -- Defined in `System.Random'
        ...plus 33 others
      In the second argument of `take', namely
        `(infinitePoissonStream 1.0 0.0 myGen)'
      In the first argument of `printAll', namely
        `(take 10 (infinitePoissonStream 1.0 0.0 myGen))'
      In a stmt of a 'do' block:
        printAll (take 10 (infinitePoissonStream 1.0 0.0 myGen))
  
  mwe3.hs:23:49:
      No instance for (Fractional r0) arising from the literal `1.0'
      The type variable `r0' is ambiguous
      Possible fix: add a type signature that fixes these type variable(s)
      Note: there are several potential instances:
        instance Fractional Double -- Defined in `GHC.Float'
        instance Fractional Float -- Defined in `GHC.Float'
        instance Integral a =&gt; Fractional (GHC.Real.Ratio a)
          -- Defined in `GHC.Real'
        ...plus two others
      In the first argument of `infinitePoissonStream', namely `1.0'
      In the second argument of `take', namely
        `(infinitePoissonStream 1.0 0.0 myGen)'
      In the first argument of `printAll', namely
        `(take 10 (infinitePoissonStream 1.0 0.0 myGen))'
  </code></pre>
  
  <p>After poking around, I "fixed" it by changing the last line:</p>
  
  <pre><code>   printAll (take 10 (infinitePoissonStream 1.0 0.0 myGen ) :: [Double])
  </code></pre>
  
  <p>Now, I wanted to use limited-precision arithmetic, so I changed the "next" line to this:</p>
  
  <pre><code>           next = rndp (start - log(rvalue) / rate)
  </code></pre>
  
  <p>and now it fails thus:</p>
  
  <pre><code>mwe3.hs:15:29:
      Could not deduce (r ~ Double)
      from the context (RandomGen g, Random r, RealFloat r)
        bound by the type signature for
                   infinitePoissonStream :: (RandomGen g, Random r, RealFloat r) =&gt;
                                            r -&gt; r -&gt; g -&gt; [r]
        at mwe3.hs:12:26-83
        `r' is a rigid type variable bound by
            the type signature for
              infinitePoissonStream :: (RandomGen g, Random r, RealFloat r) =&gt;
                                       r -&gt; r -&gt; g -&gt; [r]
            at mwe3.hs:12:26
      In the first argument of `(-)', namely `start'
      In the first argument of `rndp', namely
        `(start - log (rvalue) / rate)'
      In the expression: rndp (start - log (rvalue) / rate)
  </code></pre>
  
  <p>So I'm beginning to come to the conclusion that I <em>really</em> don't know what I'm doing. So:</p>
  
  <ol>
  <li>Can someone explain what I'm missing here?</li>
  <li>Any pointers to chapter and verse where I might stand a chance of understanding the underlying principles?</li>
  </ol>