The issue with NonEmpty
is that the last element needs to somehow cross the (:|)
in the specific case when it’s the only element, and I don’t know if that can be proven to the compiler without adding extra state. If I use the other non-empty list, it’s rather trivial:
data List1 a = One a | Cons1 a (List1 a)
{-# INLINE [0] foldr_ #-}
foldr_ :: (a -> b -> b) -> (a -> b) -> List1 a -> b
foldr_ f z = go
where
go (One a) = z a
go (Cons1 a as) = f a (go as)
{-# INLINE [1] build1 #-}
build1 :: Build a -> a -> List1 a
build1 g x = g Cons1 (One x)
{-# RULES
"foldr_/build1" forall k z (g :: forall b. (a -> b -> b) -> b -> b) x .
foldr_ k z (build1 g x) = g k (z x)
#-}
Turned out I don’t actually need it: I can instead have (a -> b -> b)
and (a -> b)
as extra arguments in the function producing the list and provided I align function arities (which I didn’t do the first time), GHC will inline it all the same.