Home > Mobile >  How can `:i` show a different type than `:t`?
How can `:i` show a different type than `:t`?

Time:12-29

When using random-fu 0.3.0.0 I get confused exploring the types for random.

Checking with :t I get

ghci> :t Data.Random.sample
Data.Random.sample
  :: (Data.Random.Distribution d t, Data.Random.StatefulGen g m,
      Control.Monad.Reader.Class.MonadReader g m) =>
     d t -> m t

But :i shows a different type

ghci> :i Data.Random.sample
Data.Random.sample ::
  (Data.Random.Sampleable d m t, Data.Random.StatefulGen g m,
   Control.Monad.Reader.Class.MonadReader g m) =>
  d t -> m t
        -- Defined in `Data.Random.Sample'

The source code seems to require the Sampleable constrain. Interestingly, there is a comment that asks for Distribution instead.

-- |Sample a random variable using the default source of entropy for the
-- monad in which the sampling occurs.
sample :: (Sampleable d m t, StatefulGen g m, MonadReader g m) => d t -> m t
sample thing = ask >>= \gen -> sampleFrom gen thing

-- |Sample a random variable in a \"functional\" style.  Typical instantiations
-- of @s@ are @System.Random.StdGen@ or @System.Random.Mersenne.Pure64.PureMT@.
-- sample :: (Distribution d a, StatefulGen g m, MonadReader g m) => d t -> m t
-- sample thing gen = runStateGen gen (\stateGen -> sampleFrom stateGen thing)

What is causing the difference between the types reported by :i and :t?

(I am not asking about how to use random-fu, there are examples that work in their github)

CodePudding user response:

Here's a similar example of the same phenomenon with more familiar constraints:

> f :: (Eq a, Ord a) => a -> Bool; f x = x > x
> :i f
f :: forall a. (Ord a, Eq a) => a -> Bool
> :t f
f :: forall {a}. Ord a => a -> Bool

GHC has noticed that the Eq constraint isn't needed in the type, because the Ord constraint already guarantees it*:

> :i Ord
class Eq a => Ord a where
<snip>

Your situation is similar, just with a more complicated class. Stated explicitly: :i gives information about the definition as written by the programmer, parroting back exactly what was written as the type signature (and so only works on lone identifiers), while :t works on any expression but runs a full type inference algorithm, including constraint simplification.

* You might wonder whether it noticed that == wasn't used, and this is the real reason that the Eq constraint isn't needed. But no; change the definition to f x = x > x || x == x and the Eq constraint will still be omitted from :t f.

  • Related