Я выполняю следующий вызов метода Haskell
rollD6 :: (RandomGen g, Int a) => Int -> ([a], g)
rollD6 times = roll Die6 times (mkStdGen 6)
rollD6InRange :: (RandomGen g, Int a) => Int -> Int -> Int -> ([a], g)
rollD6InRange times start end = rollR Die6 times start end (mkStdGen 6)
class Roll a where
roll :: (RandomGen g) => a -> Int -> g -> ([Int], g)
rollR :: (RandomGen g) => a -> Int -> Int -> Int -> g -> ([Int], g)
instance Roll Die where
roll Die6 times = generateIntRandomsArray 1 6 times
roll Die4 times = generateIntRandomsArray 1 4 times
roll Die20 times = generateIntRandomsArray 1 20 times
roll Die100 times = generateIntRandomsArray 1 100 times
rollR Die6 times first last = generateIntRandomsArray first last times
rollR Die4 times first last = generateIntRandomsArray first last times
rollR Die20 times first last = generateIntRandomsArray first last times
rollR Die100 times first last = generateIntRandomsArray first last times
generateIntRandomsArray :: (Eq a, Random a, Num a, RandomGen g) => a -> a -> a -> g -> ([a], g)
generateIntRandomsArray start end = generate
where generate 0 generator = ([], generator)
generate numberElements generator =
let (value, newGenerator) = randomR (start,end) generator
(restOfList, finalGenerator) = generate (numberElements-1) newGenerator
in (value:restOfList, finalGenerator)
и я получаю следующую ошибку
src/Merp/Die/Boundary/RollADie.hs:11:26: error:
• Expected kind ‘* -> Constraint’, but ‘Int’ has kind ‘*’
• In the type signature:
rollD6 :: (RandomGen g, Int a) => Int -> ([a], g)
|
11 | rollD6 :: (RandomGen g, Int a) => Int -> ([a], g)
| ^^^^^
src/Merp/Die/Boundary/RollADie.hs:14:32: error:
• Expected kind ‘* -> Constraint’, but ‘Int’ has kind ‘*’
• In the type signature:
rollD6InRange :: (RandomGen g, Int a) =>
Int -> Int -> Int -> ([a], g)
|
14 | rollD6InRange :: (RandomGen g, Int a) => Int -> Int -> Int -> ([a], g)
| ^^^^^
Я поигрался с параметрами звонка, но так и не смог понять, что происходит. Подскажите, пожалуйста, что там осталось?
Я также ожидал бы, что повторение будет выполняться вне класса; сделать так, чтобы в методах были только вещи, которые различаются между экземплярами. rollR
вероятно, вообще не должно существовать; generateIntRandomsArray
уже делает то же самое, без странного игнорируемого первого аргумента. Почему gIRA
заставляет счетчик повторений иметь тот же тип, что и генерируемый случайный тип? 2/2
Int
не является классом типов, поэтому:
rollD6 :: (RandomGen g, Int a) => Int -> ([a], g)
rollD6 times = roll Die6 times (mkStdGen 6)
не имеет особого смысла: вы заменяете a
на Int
, поэтому:
rollD6 :: RandomGen g => Int -> ([Int], g)
rollD6 times = roll Die6 times (mkStdGen 6)
То же самое справедливо и для rollD6InRange
.
Я бы также посоветовал сохранить тип диапазона и количество элементов отдельно, поэтому:
generateIntRandomsArray :: (Random a, Integral b, RandomGen g) => a -> a -> b -> g -> ([a], g)
generateIntRandomsArray start end = generate
where
generate 0 generator = ([], generator)
generate numberElements generator =
let (value, newGenerator) = randomR (start, end) generator
(restOfList, finalGenerator) = generate (numberElements -1) newGenerator
in (value : restOfList, finalGenerator)
это позволяет нам, например, генерировать из последовательности Char
, Bool
, Float
или чего-либо еще, что является экземпляром Random [Hackage], например:
ghci> generateIntRandomsArray 'a' 'z' 10 (mkStdGen 0)
("nlrkwldbji",1695805043 1336516156)
@Yago: Обычно это не то, что вы обычно делаете, но с некоторыми расширениями (например, TypeFamilies
) вы можете использовать Int ~ a
в качестве ограничения; «оператор» ~
говорит, что a
и Int
должны быть унифицированы, чтобы функция могла выполнять проверку типа (т. е. он утверждает, что a
должно быть Int
).
Хороший . Спасибо за помощь . Просто новичок, пытающийся научиться.
Этот API очень странный. Неужели еще есть подобные экземпляры? Если нет, не делайте это классом. Но если это так, я бы, по крайней мере, ожидал, что это будет класс типа с несколькими параметрами или класс со связанным типом для выходных значений; конечно, не все случайные «спецификации» предназначены для производства
Int
. 1/2