当使用random-fu 0.3.0.0时,我对探索random
的类型感到困惑。
检查我得到:t
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
但:i
显示了不同的类型
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'
源代码似乎需要Sampleable
约束。有趣的是,有一条评论要求Distribution
。
-- |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)
是什么导致了:i
和:t
报告的类型之间的差异?
(我不是在问如何使用random-fu
,有一些示例可以在他们的 github 中工作)
下面是具有更熟悉约束的相同现象的类似示例:
> 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 注意到类型中不需要Eq
约束,因为Ord
约束已经保证了这一点*:
> :i Ord
class Eq a => Ord a where
<snip>
你的情况是相似的,只是类更复杂。 明确说明::i
提供有关程序员编写的定义的信息,准确地回馈作为类型签名编写的内容(因此仅适用于单独的标识符),而:t
适用于任何表达式,但运行完整的类型推断算法,包括约束简化。
*您可能想知道它是否注意到未使用==
,这是不需要Eq
约束的真正原因。但是没有;将定义更改为f x = x > x || x == x
,Eq
约束仍将从:t f
中省略。