This is an excellent use case for applicative style. You can replace your entire snippet (after importing Control.Applicative
) with
Node <$> numberNode x <*> numberTree t1 <*> numberTree t2
Think of the applicative style (using <$>
and <*>
) as "lifting" function application so it works on functors as well. If you mentally ignore <$>
and <*>
it looks quite a lot like normal function application!
Applicative style is useful whenever you have a pure function and you want to give it impure arguments (or any functor arguments, really) -- basically when you want to do what you specified in your question!
The type signature of <$>
is
(<$>) :: Functor f => (a -> b) -> f a -> f b
which means it takes a pure function (in this case Node
) and a functor value (in this case numberNode x
) and it creates a new function wrapped "inside" a functor. You can add further arguments to this function with <*>
, which has the type signature
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
As you can see, this is very similar to <$>
only it works even when the function is wrapped "inside" a functor.