13

Say I have a mean function defined like so:

mean xs = sum xs / (fromIntegral $ length xs)

but I want it in some tacit form, like this:

mean = sum / (fromIntegral . length)

Is there a built-in Haskell way to do something along these lines without having to build up my own tacit function (something like this):

tacit :: (a -> b -> c) -> (d -> a) -> (d -> b) -> d -> c
tacit a b c i = a (b i) (c i)

In this form, the function looks like this:

mean = tacit (/) sum (fromIntegral . length)

but it feels like there might be a way to avoid having to use an explicit function such as this. I'm just wondering; is there some way to do this that is built in to Haskell?

3
  • 2
    See squing.blogspot.com/2008/11/beautiful-folding.html, conal.net/blog/posts/more-beautiful-fold-zipping Commented Aug 21, 2012 at 20:13
  • 1
    The technical term for what you call "tacit" is "point free" (or sometimes "pointless" for people being sarcastic). The term "point" comes from topology, and it actually refers to the variables. Commented Aug 22, 2012 at 19:18
  • @PaulJohnson, "tacit" is the term used by the J programming language (and maybe others?) to refer to what is more commonly known as "point free". Commented Aug 30, 2012 at 16:06

2 Answers 2

20

Applicative functors work pretty well here.

import Control.Applicative

mean = (/) <$> sum <*> (fromIntegral . length)
Sign up to request clarification or add additional context in comments.

Comments

14

Yes, your tacit function is liftM2 in the (->) r monad (liftM2 is in Control.Monad, and the function instance of Monad is in Control.Monad.Instances).

I found this using the pointfree program (you can install it via cabal install pointfree), invoked as:

$ pointfree '\xs -> sum xs / (fromIntegral $ length xs)'

(in a Unix terminal)

8 Comments

And then you can make a Num instance for (->) r and then mean = sum / (fromIntegral . length) will actually work.
@SjoerdVisscher: you need Fractional too because of (/). Just tried it and confirmed that's all you need.
And an amusing addition to that is that once you have the Num r => Num (a -> r) instance, you can add addition to itself: (+) + (+) becomes a well-typed expression (equivalent to \x y -> (x + y) + (x + y)).
@sacundim Ah, right. And 1 2 3 4 is also a well-typed expression. It's clear why this is not a built-in instance.
Heh, I didn't think of that one. But what makes it worse is that if a module of yours imports any module that uses this instance directly or indirectly, you're going to get this instance. So one should really wrap it with a newtype—in which case the extra syntactic overhead means that you might as well use Applicative.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.