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
.