Запуск генератора ежа с состоянием - PullRequest
3 голосов
/ 27 сентября 2019

Я взял следующий генератор дерева:

genTree0 :: MonadGen m => m (Tree String)
genTree0 =
  Gen.recursive Gen.choice
    [ Node "X" [] ]
    [ Node "X" <$> Gen.list (Range.linear 0 20) genTree0 ]

и переписал его в состояние с состоянием:

genTree1 :: (MonadGen m, MonadState Int m) => m (Tree String)
genTree1 =
  Gen.recursive Gen.choice
    [ (`Node` []) <$> next ]
    [ Node <$> next <*> Gen.list (Range.linear 0 20) genTree1 ]
  where
    next :: MonadState Int m => m String
    next = fmap show (get <* modify (+1))

Но тогда как я мог прежде написать, например:

Gen.sample genTree >= putStrLn . drawTree

Я больше не могу делать это с версией с состоянием, потому что, конечно, я не инициализировал состояние:

> Gen.sample genTree

<interactive>:149:12: error:
    • No instance for (MonadState Int Identity)
        arising from a use of ‘genTree’

Попытка исправить это (предполагая, но не будучи полностью убежденной, что GenT и StateT коммутируют),

> Gen.sample (evalStateT genTree 0)

<interactive>:5:23: error:
    • Could not deduce (MonadGen
                          (StateT Int (Hedgehog.Internal.Gen.GenT Identity)))

Я думаю, что есть очень маленькая, последняя часть, связанная с семействами типов, которую я не лажу.Что бы это могло быть?Если, например, я добавлю

genTree1 :: ( MonadGen m
            , MonadState Int m
            , GenBase m ~ Identity)
         => m (Tree String)

(просто потому, что я видел это раньше)

Вместо этого я получу еще одну ошибку,

> Gen.sample (runStateT genTree 0)

<interactive>:15:23: error:
    • Couldn't match type ‘GenBase (StateT Int (GenT Identity))’
                     with ‘Identity’

К сожалению, вВ этот момент я просто начинаю неправильно угадывать, какое ограничение применять.

Обновление: В другом ключе я пытался создать определенный стек монадных преобразователей, начиная с genTree0 и genTree1 имеют довольно общие подписи:

newtype StateGen s a = StateGen { runStateGen :: StateT s (GenT IO) a }
  deriving ( Functor, Applicative, Monad
           , MonadState s
           , MonadGen
           , MonadIO
           )

, но это также немного неправильно по отношению к.по крайней мере MonadGen.

Что я должен здесь напечатать, чтобы начать, и еще лучше, где я могу научиться лучшему способу, чем гадание?

...