我正在尝试构建一个递归函数,为简单起见,我们假设它需要一个列表并构建一个数组和一个列表。因为我需要在构建数组时读取和写入数组,所以我使用了一个可变数组,因此我可以进行恒定的读写操作。所以签名和函数看起来如下:
f :: [a] -> ST s ([a], STArray s Int a) -> ST s ([a], STArray s Int a)
f (x:xs) curr_arr =
case blah of
... -> f xs new_arr
f [] curr_arr = curr_arr
我想要一个带有以下签名的函数h
:
h :: Int -> Int -> a -> [a] -> (Array Int a, [a])
我希望它有大致以下的实现:
h lbound ubound default_a xs = g (f xs (newArray lbound ubound default_a))
问题是,我需要一个带有此签名的函数g
:
ST s ([a], STArray s Int a) -> (Array Int a, [a])
但我似乎无法将runST
和runSTArray
合在一起来实现这一目标。
无论如何都要实施g
,或者我应该首先使f
的签名完全不同?
答案 0 :(得分:0)
您应该使用Monad
ST s
实例来实现对f
的递归调用(及其结果的组合):更改f
' s输入
f :: [a] -> ([a], STArray s Int a) -> ST s ([a], STArray s Int a)
这意味着f
中的递归调用看起来像
f xs curr = do
xs' <- ...
curr' <- ...
next <- f xs' curr'
combine curr next
然后runST
它在h
完成(runSTArray
并不直接在这里工作,因为你的[a]
也在旁边):< / p>
h lo hi x0 xs = runST $ do
curr <- newArray lo hi x0
(ys, mArr) <- f xs (xs, curr)
arr <- freeze mArr
return (ys, arr)
这是有效的,因为在最后一个表达式ys :: [a]
和arr :: Array Int a
中,所以两者都不取决于s
的选择。