我使用了以下树生成器:
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’
不幸的是,在这一点上,我只是开始猜测在哪个约束条件上适用。
更新:换句话说,我尝试构造一个特定的monad变压器堆栈,因为genTree0
和genTree1
具有非常通用的签名:
newtype StateGen s a = StateGen { runStateGen :: StateT s (GenT IO) a }
deriving ( Functor, Applicative, Monad
, MonadState s
, MonadGen
, MonadIO
)
但是这也有点错误。至少MonadGen
。
我要在这里输入什么才能开始,更好的是,在哪里我可以学到比猜测更好的方法?