I have written this function:
-- Either exact match or is suffix of ".example.com" (mind the dot)
-- This prevents for overlapping like "myexample.com"
isDomainOf :: B.ByteString -> B.ByteString -> Bool
isDomainOf a b = (a == b) || a `B.isSuffixOf` (B.append "." b)
If I apply pointless to the function I get:
isDomainOf = ap (ap . ((||) .) . (==)) ((. B.append ".") . B.isSuffixOf)
Which is obviously even longer and harder to read than the pointful version.
The problem is the or operator, because I can't just write the left and right hand sides of (||)
like this:
isDomainOf = (==) || (. append ".") . isSuffixOf
Is there any better way to express this?
The general scheme is that you have
foo :: A -> B -> C -- foo = (==) :: BStr->BStr->Bool
bar :: A -> B -> D -- bar = (\a b -> a`isSuffixOf`(':':b)) :: BStr->BStr->Bool
comb :: C -> D -> E -- comb = (||) :: Bool->Bool->Bool
and want to express \a b -> comb (foo a b) (bar a b)
. First of course it's a good idea to hoogle for that specific combinator, but it's a bit too crazy for this to expect results.
To try making a point-free version ourselves (as bheklir remarks, it's probably a bad idea here to consider that in the first place), first observe it becomes much easier when the infixes aren't curried.
foo' :: (A,B) -> C
bar' :: (A,B) -> D
why, if you then unify (A,B) ~ P
, we simply need to put foo'
and bar'
in parallel and feed the results to comb
. With the Arrow
combinators, this looks thus:
uncurry comb . (foo' &&& bar')
which isn't too bad. Of course, writing out all with the necessary uncurrying makes it nevertheless a nightmare to read:
curry $ uncurry (||) . (uncurry(==) &&& \(a,b) -> a`isSuffixOf`(':':b))
Since we still have a lambda in there, it's still not point-free anyway; though that one can of course be unpointed as well:
curry $ uncurry (||) . (uncurry(==) &&& uncurry(((':':).) . isSuffixOf))