# Semantic Editor Combinators - one of my favorite blog posts

I wanted to squeeze this blog post into my Best Haskell Papers of 2009 article, but it unfortunately was written in late 2008. For your enjoyment, here is the entry below.

## Semantic Editor Combinators - Conal Elliott [link]

Strictly speaking this isn’t a paper. On the other hand, the functional pearl therein is a must for any Haskeller’s box of tools. The essence of the presented technique allows one to write easy to understand transforms of functions, or function like things. For example:

f :: Int -> (Int,Char) -> String -- Want to convert into type g . . . g :: Int -> (Int,Int) -> String -- with transformer z. z :: Int -> Char -- Implementation using semantic editor combinators: g = (result . argument . second) z f

The g implementation can be read backwards as “apply the z transformation to the second element of the tuple of the argument of the result of f”. Recall that functions only have one argument and one result and that the result of a curried function is another function.

It takes a bit of getting used to, but it is definitely worth the investment in time learning. It frequently makes code more elegant and concise.

Note, if you ever get stumbled by an (fmap.fmap.fmap) in code, this is where to go.

[...] a short note on a blog post that I really wanted to be on this list. January 18th, 2010 in [...]

Hi David. Thanks for the plug! I’m glad you like the post.

Would you do me a favor and fix the title to be “Semantic Editor Combinators”? (Note “combinator” rather than “combiner”.) The building blocks are combinators (higher-order functions, or more generally purely functional library elements) and more specifically lifters, but mainly not combiners of editors. I like to stem nomenclature confusions before they spread much.

@Conal: Thanks for pointing out my mistake. I’ve made the fix.

z :: Int -> Char

should be

z :: Char -> Int ?

Should z be Char -> Int?

@Stephen,Jeremy: Nope. I agree it’s counterintuitive at first glance.

If you have a function

`f :: a -> b`

and you’d like to make a function`g :: c -> b`

out of it, realize that you’d need some function ‘h :: c -> a’ where`g = f . h`

.So the rule is, if you have an argument of type

`a`

that you’d like to be of type`b`

, you need a function`b->a`

. If you have a return type`a`

that you’d like to be of type`b`

, you need a function`a->b`

.