Проблема в том, что choose (0, 1)
не производит Int
, оно производит Gen Int
.
Вы рассматриваете это, как если бы это было Int
в этом выражении:
pure $ g (\i -> i + choose (0, 1))
Поскольку Gen Int
является монадой, вам необходимо связать ее, чтобы использовать результат «выбора».
Примерно так:
instance Arbitrary Q where
arbitrary :: Gen Q
arbitrary = do
choice <- choose (0, 1)
return $ g (\i -> i + choice)
Отвечая на отредактированный вопрос:
Проблема все та же, вы пытаетесь использовать Gen Int
, как если бы это был Int
.Вы можете связать несколько раз внутри do
.
Вот решение:
instance Arbitrary Q where
arbitrary :: Gen Q
arbitrary = do
len <- choose (1, 5)
choice <- choose (0, 1)
return $ g len (\i -> i + choice)
Ответ на отредактированный, отредактированный вопрос :
Вы должны распространять побочные эффекты где-то, это просто означает, что вам нужно запускать choose
len
раз.Поскольку g
является «библиотечной» функцией, я предполагаю, что вы не можете ее контролировать и не можете ее изменить.Обратите внимание, что приведенное ниже решение является уродливым, поскольку мне нужно использовать частичную функцию (!!)
, а также потому, что она довольно медленная (возможно, есть лучший способ сделать это, но я не могу ее найти).
Хитрость здесь в том, что я сопоставляю функцию, которая возвращает len
Gen Int
, и затем запускает их все, производя список выбранных чисел (см. mapM
описание дляподробнее).
instance Arbitrary Q where
arbitrary :: Gen Q
arbitrary = do
len <- choose (1, 5)
choices <- mapM (\_ -> choose (0, 1)) [1 .. len]
return $ g len (\i -> i + (choices !! i))