Matthew Ibbetson
Matthew Ibbetson

Reputation: 23

Defining an alternative Psi combinator in Haskell

I've been working on a simple Leetcode problem in Haskell: Max Count of Pos & Neg Integer:

-- First solution
maximumCount :: [Int] -> Int
maximumCount = liftM2 max (length . filter (> 0)) (length . filter (< 0))

-- Custom combinator that's ALMOST the Psi combinator
-- abcde.a(b(ce)(b(de))
myCombinator :: (c -> c -> d) -> (a -> b -> c) -> a -> a -> b -> d
myCombinator f g x y z = f (g x z) (g y z)

-- Second solution
maximumCount' :: [Int] -> Int
maximumCount' = myCombinator max (length .: filter) (> 0) (< 0)

I haven't been able to find an existing combinator that behaves this way. But I am certain that it can be defined by combining existing combinators. I'm still very new to combinatory logic, so I may be unaware of an existing equivalent or perhaps a methodology for deriving a combinator spelling.

I attempted to write a function to combine arguments for a function such that they would be in the correct shape for the on function, but I was unable to get a proper definition.

Upvotes: 2

Views: 126

Answers (1)

K. A. Buhr
K. A. Buhr

Reputation: 50864

It looks like on operating over a reader (->) a, so the following ought to work. Note that I started by lifting the binary operator into the reader and invoking on:

myCombinator op f = on (liftA2 op) f

and then simplified the result:

import Control.Applicative
import Data.Function

myCombinator :: (c -> c -> d) -> (a -> b -> c) -> a -> a -> b -> d
myCombinator = on . liftA2

Upvotes: 2

Related Questions