2

我有一个状态机模型

newtype State (v :: * -> *) = State (M.Map (Var UUID v) DataPerItem)
    deriving (Eq, Show)

然后我有一个Command gen exec [Update update]返回exec列表UUID,即它有类型

exec :: action -> m [UUID]

这反过来意味着update需要这样的类型

update :: State v -> action -> Var [UUID] v -> State V

AFAICS 为了真正更新我的模型,我需要将其Var [UUID] v转换为[Var UUID v]. 我一直在盯着 Hedgehog 中的函数看了一段时间,但什么都没有跳出来……还是我再次认为这一切都错了?:)

4

1 回答 1

1

这是行不通的,但有一个很好的理由。

将状态机测试视为自动编写测试程序,其中每个测试程序都Var a Symbolic作为程序中的一个绑定。

所以想象一下我正在测试一个小缓冲区,带有操作create :: Size -> Buf和.put :: Buf -> Int -> IO ()get :: Buf -> IO Int

我可以手动进行单元测试。

test :: TestT IO ()
test = do
  buf <- create 3
  put buf 5
  put buf 10
  put buf 20
  retrieved <- get buf
  retrieved === Just 5

使用适当的命令,hedgehog 也可以生成这个精确的测试

test :: TestT IO ()
test = do
  Var 1 = create 3
  Var 2 = put (Var 1) 5
  Var 3 = put (Var 1) 10
  Var 4 = put (Var 1) 20
  Var 5 = get (Var 1)
  Var 5 === Just 5

所以每次执行都有一个变量名。

当你想要这样的东西时:

splitNames :: Var [UUID] v -> [Var UUID v]

您所要求的本质上是执行列表中的每个返回都被赋予其自己的变量名。然后程序的其余部分可以使用这些变量名。我能想到的最好的展示方式是:

test :: TestT IO ()
test = do
  Var 1 = returnSomeNumberOfItems
  Var 2 = Var 1 ! 0
  Var 3 = Var 1 ! 1

现在这里的问题是我们只是不知道返回的列表有多长returnSomeNumberOfItems;我们还没有运行它;没有办法安全地做到这一点。

于 2020-06-02T01:31:42.827 回答