haskell - tube - ¿Cómo puedo hacer que mi regla se dispare?
mafer neyra cosas de chicas (1)
Estoy trabajando en las reglas de fusión de fromListN
para fromListN
en Data.Primitive.Array
, y estoy un poco atascado. La función se ve así:
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 #-}
fromListN_too_short
y fromListN_too_long
son solo llamadas de error.
Mis reglas de reescritura son
{-# 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
#-}
donde se definen los ayudantes
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 #-}
La primera regla de reescritura parece hacerlo bien. La segunda regla de la escritura es el problema. Parece que nunca puedo hacer que se dispare. ¿Alguien puede ofrecer una sugerencia?
Nota: Sé que podría fusionarme directamente con build
y build
para evitar tener que responder, pero ... no es una visión bonita.
El principal problema parece ser un error de mi parte. En
"fillArrayN/list" [1] forall n mary xs i.
foldr (fillArray_go n mary) (fillArray_stop n) xs i = fillArrayN n mary xs i
foldr
es Data.Foldable.foldr
, que es un método de clase y por lo tanto no funciona en el LHS de una regla. Solucionar este problema hace que la regla de reescritura funcione en casos simples.
Desafortunadamente, cuando fromListNArray
fusiona con el fromListNArray
(que suele ocurrir cuando se aplica a las listas adjuntas), la regla no se activa por otra razón. GHC crea una función para fillArray_go n mary
, y no la fillArray_go n mary
. Todavía no entiendo por qué sucede esto.