<br><div><span class="gmail_quote">On 10/29/07, <b class="gmail_sendername">Tim Newsham</b> <<a href="mailto:newsham@lava.net">newsham@lava.net</a>> wrote:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
I would love to have the ability to define binary operator modifiers.<br>For example:<br><br> f \overline{op} g = liftM2 op f g<br> f \overleftarrow{op} n = liftM2 op f (return n)<br> n \overrightarrow{op} g = liftM2 op (return n) f
<br> \widehat{f} x = liftM f x<br><br>so that for example you could define functions like:<br><br> (*3) \overline{+} (/2)<br><br>and<br><br> 3 \overrightarrow{+} \widehat{read} getContents<br><br>Obviously you could write this out the long way:
<br><br> liftM2 (3+) $ liftM read getContents<br><br>or go through the trouble of defining a bunch of binops<br><br> f <+> g = liftM2 (+) f g<br> n +> g = return n <+> g<br> f <+ n = f <+> return n
<br> read' = liftM read<br><br> (*3) <+> (/2)<br> 3 +> read' getContents<br><br>but doing this for more than one or two operators gets tedious<br>quickly...<br><br>Is there any way in Haskell to modify binops in this way and still
<br>be able to use them infix? If not, has anyone considered supporting<br>strange syntaxes like this?</blockquote><div><br>I've wanted this at times, too, due to using a lot of J a year or so ago. J has some weird parsing/semantics rules so that f g h essentially means liftM2 g f h. For example, avg =. +/ % # is the J equivalent of avg = liftM2 (/) sum length. Anyway, the closest you can get in Haskell is something like this, using the
<a href="http://www.haskell.org/pipermail/haskell-cafe/2002-July/003215.html">infix expressions of Ken Shan and Dylan Thurston</a>:<br><br>import Control.Monad<br>import Control.Monad.Instances<br><br>infixr 0 -:, :-<br><br>
data Infix f y = f :- y<br>x -: f :- y = x `f` y<br><br>ov op = liftM2 op<br>ovL op f n = liftM2 op f (return n)<br>ovR op n f = liftM2 op (return n) f<br>hat f = liftM f<br><br>*Main> :t (*3) -:ov (+):- (/2)<br>(*3) -:ov (+):- (/2) :: forall a1. (Fractional a1) => a1 -> a1
<br>*Main> ((*3) -:ov (+):- (/2)) 7<br>24.5<br>*Main> :t 3 -:ovR (+):- ((hat read) getContents)<br>3 -:ovR (+):- ((hat read) getContents) :: forall a. (Num a, Read a) => IO a<br><br>It works (?), but it's pretty ugly and hardly seems worth it, unfortunately.
<br><br>-Brent</div></div>