我的工作列表融合规则fromListN中Data.Primitive.Array,和我有点卡住了.该函数如下所示:
fromListNArray :: Int -> [a] -> Array a
fromListNArray !n l =
createArray n fromListN_too_short $ \mi ->
let go i (x:xs)
| i < n = writeArray mi i x >> go (i+1) xs
| otherwise = fromListN_too_long
go i [] = unless (i == n) fromListN_too_short
in go 0 l
{-# NOINLINE fromListNArray #-}
Run Code Online (Sandbox Code Playgroud)
fromListN_too_short并且fromListN_too_long只是错误调用.
我的重写规则是
{-# RULES
"fromListNArray/foldr" [~1] forall n xs.
fromListNArray n xs = createArray n fromListN_too_short $ \mary ->
foldr (fillArray_go n mary) (fillArray_stop n) xs 0
"fillArrayN/list" [1] forall n mary xs i.
foldr (fillArray_go n mary) (fillArray_stop n) xs i = fillArrayN n mary xs i
#-}
Run Code Online (Sandbox Code Playgroud)
帮助者的定义
fillArrayN :: Int -> MutableArray s a -> [a] -> Int -> ST s ()
fillArrayN !n !mary xs0 !i0 = go i0 xs0
where
go i (x:xs)
| i < n = writeArray mary i x >> go (i+1) xs
| otherwise = fromListN_too_long
go i [] = unless (i == n) fromListN_too_short
{-# NOINLINE fillArrayN #-}
fillArray_go :: Int
-> MutableArray s a
-> a
-> (Int -> ST s ())
-> Int
-> ST s ()
fillArray_go !n !mary = \x r i ->
if i < n
then writeArray mary i x >> r (i + 1)
else fromListN_too_long
{-# INLINE CONLIKE [0] fillArray_go #-}
fillArray_stop :: Int -> Int -> ST s ()
fillArray_stop !n = \i -> unless (i == n) fromListN_too_short
{-# INLINE [0] fillArray_stop #-}
Run Code Online (Sandbox Code Playgroud)
第一次重写规则似乎没问题.第二个回写规则是问题所在.我似乎永远无法解雇它.任何人都可以提出建议吗?
注意:我知道我可以直接融合build并augment避免回写,但它不是一个美丽的景象.
主要问题似乎是我的错误。在
"fillArrayN/list" [1] forall n mary xs i.
foldr (fillArray_go n mary) (fillArray_stop n) xs i = fillArrayN n mary xs i
Run Code Online (Sandbox Code Playgroud)
isfoldr是Data.Foldable.foldr一个类方法,因此不适用于规则的 LHS。解决此问题可以使回写规则在简单情况下发挥作用。
不幸的是,当fromListNArray与 融合时augment(通常在应用于附加列表时发生),该规则由于另一个原因而无法触发。GHC 为 创建一个函数fillArray_go n mary,并且不内联它。我仍然不明白为什么会发生这种情况。
| 归档时间: |
|
| 查看次数: |
212 次 |
| 最近记录: |