Проблема в том, что useRNG
может генерировать все виды чисел (любой экземпляр Random
) и работать во всех видах монад (любая монада состояний, состояние которой является экземпляром RandomGen
), как это может бытьвидно из его предполагаемой сигнатуры:
GHCi> :t useRNG
useRNG
:: (MonadState s m, RandomGen s, Random a, Num a) =>
[a] -> a -> m [a]
... но когда вы используете ее, вы не указали , какие конкретные типы вам действительно нужны.
Есливы устраняете неоднозначность с помощью сигнатуры типа:
test :: State StdGen [Int]
test = foldM useRNG [] [0 .. 50]
, тогда она работает нормально.Вы также можете сделать это, поставив сигнатуру типа на useRNG
:
useRNG :: [Int] -> Int -> State StdGen [Int]
Теперь вы можете подумать: если useRNG
отлично работает со всеми этими типами, то почему не может test
тоже?Ответ - ограничение мономорфизма , которое довольно загадочно и не очень нравится многим пользователям Haskell.Вы можете избежать этого, поместив
{-# LANGUAGE NoMonomorphismRestriction #-}
вверху вашего файла или указав test
явную сигнатуру типа:
test :: (RandomGen g, Random a, Num a, Enum a, MonadState g m) => m [a]
Вы можете найти правильную сигнатуру типас GHCi:
GHCi> :t foldM useRNG [] [0 .. 50]
foldM useRNG [] [0 .. 50]
:: (MonadState s m, RandomGen s, Random b, Num b, Enum b) => m [b]
(я написал явную сигнатуру типа перед проверкой с помощью GHCi, поэтому у меня она немного отличается.)
Однако эта сигнатура типа немного слишком полиморфный для практического использования - вы будете в основном устранять неоднозначность до тех пор, пока не будете фактически использовать результат - поэтому я бы предложил конкретизировать его в этом случае.Например, вы можете оставить test
универсальным для типа случайного числа без ненужного полиморфизма над монадой состояния и типом генератора:
test :: (Random a, Num a, Enum a) => State StdGen [a]
Вы также можете рассмотреть возможность использования MonadRandom , который включает все стандартные средства генерации случайных чисел в интерфейсе на основе монад, поэтому вам не нужно:)