`Нет экземпляра для System.Random.Random` в пользовательском классе типов при использовании` choose` - PullRequest
0 голосов
/ 23 октября 2018

Я делаю упражнение в программировании на Хаскеле из Первых принципов.Он просит меня сгенерировать равные вероятности, и 1/3, 2/3 вероятности для каждого из:

data Fool =
  Fulse
  | Frue
  deriving (Eq, Show)

И мой ответ

module Random where

-- import Test.Hspec
import Test.QuickCheck

data Fool =
  Fulse
  | Frue
  deriving (Eq, Show)


genFool :: Gen Fool
genFool = choose (Fulse, Frue)

genFool' :: Gen Fool
genFool' = do
  frequency [(2, return Fulse)
            ,(1, return Frue)]

, но genFool неверен.Сообщение об ошибке:

../chap14/random.hs:13:11: error:
    • No instance for (System.Random.Random Fool)
        arising from a use of ‘choose’
    • In the expression: choose (Fulse, Frue)
      In an equation for ‘genFool’: genFool = choose (Fulse, Frue)
   |
13 | genFool = choose (Fulse, Frue)
   |           ^^^^^^^^^^^^^^^^^^^^

Ранее у меня был такой код:

genBool :: Gen Bool
genBool = choose (False, True)

, который работает правильно.Я думаю, что может быть несколько предопределенных instance из System.Random.Random Fool, чтобы заставить choose работать.

Что я должен сделать, чтобы моя версия genFool компилировалась?

ИКстати, почему return Fulse во втором genFool' типа Gen Fool?

1 Ответ

0 голосов
/ 23 октября 2018

Функция choose модуля Test.Quickcheck имеет следующую сигнатуру типа:

choose :: Random a => (a, a) -> Gen a 

Итак, если вы планируете использовать функцию choose для типа Fool, она должна бытьсделал экземпляр Random класса типов, как видно из приведенной выше сигнатуры типа.

Здесь определен Случайный класс типов .Требуется либо минимальная реализация либо randomR, либо random.

Поскольку ваш тип Fool имеет только два значения, он изоморфен типу Bool.Таким образом, вы можете определить функцию, отображающую значения соответствующим образом:

mapBool :: Bool -> Fool
mapBool False = Fulse
mapBool True = Frue

И затем вы можете определить экземпляр класса типов для вашего типа:

instance Random Fool where
    random g = let (b :: Bool, g') = random g
               in (mapBool b, g')
    randomR _ g = (random g) -- Note that this doesn't work correctly. You need to pattern match and fix this.

Приведенный выше код должен заставить ваш модуль компилироватьсяхорошо.

...