functortypecheckingapplicativeidris2combinatory-logic

Idris: Cannot use functions as applicative functors?


In Haskell I am wont to use liftA2 on functions as the S' combinator. This works because the Haskell STL instantiates Functor and Applicative for functions (see https://hackage.haskell.org/package/base-4.12.0.0/docs/src/GHC.Base.html#line-818). As far as I could find, the Idris STL does not do this (besides the fact that I also couldn't find liftA2 in the STL), so I thought I'd do it myself. Only, it doesn't seem to work, but maybe I don't know Idris well enough, as I only first tried it today.

I am able to instantiate Functor and Applicative for \b => a -> b, but the typesystem does not seem able to figure out that when I use something of type a -> b, that the applicative functor is supposed to be \b => a -> b.

I have the following code:

Functor (\b => a -> b) where
  map = (.)

Applicative (\b => a -> b) where
  pure = const
  (<*>) f g x = f x (g x)

liftA2 : (Functor f, Applicative f) => (a -> b -> c) -> f a -> f b -> f c
liftA2 = (<*>) .: map

S' : (b -> c -> d) -> (a -> b) -> (a -> c) -> a -> d
S' = liftA2

But the definition of S' gives the following error:

Error: While processing right hand side of S'. Can't find an implementation for (Functor ?f, Applicative ?f).

Helpers:16:6--16:12
 12 | liftA2 : (Functor f, Applicative f) => (a -> b -> c) -> f a -> f b -> f c
 13 | liftA2 = (<*>) .: map
 14 |
 15 | S' : (b -> c -> d) -> (a -> b) -> (a -> c) -> a -> d
 16 | S' = liftA2
           ^^^^^^

Solution

  • If you name your functor or applicative, like [Foo] Functor ..., then call it with map @{Foo} it might work, but generally it's not practical to implement and use interfaces for functions in Idris. It's possible but not practical. You could wrap your function in a thin data type and implement functor and applicative for that