I come from a Lisp background, so the concepts of functional programming
come very naturally to me, but I'm having the very devil of a time
wrapping my brain around the syntax. My understanding is that:
f a b
means (using Scheme notation): (f a b) which is equivalent (thanks to
currying) to ((f a) b) UNLESS 'a' has been defined as an infix operator,
in which case "f a b" means (a f b) == ((a f) b).
Question 1: Is that right?
Question 2: When you're reading code and you see "a b c" how are you
supposed to know whether it means ((a b) c) or ((b a) c)?
Thanks,
rg
> Ron Garret <rNOS...@flownet.com> writes:
> >My understanding is that:
> >f a b
> >means (using Scheme notation): (f a b)
>
> To me, the notion of a meaning does not make sense unless the
> language to be used for interpretation is given. »Functional
> programming« is not a language.
My understanding was that there is a common syntactic convention used in
most modern functional languages (i.e. ML, Haskell, Miranda...). But if
there isn't, then let's constrain it to Haskell. That seems to be what
all the cool kids are using nowadays.
rg
> Question 1: Is that right?
Looks about right.
> Question 2: When you're reading code and you see "a b c" how are you
> supposed to know whether it means ((a b) c) or ((b a) c)?
With Haskell, it's what characters are used. Words drawn from [a-z] can
only become infix operators when you put them in backquotes. You'll see
all the Haskell infix operators are +, >>, etc. and things like `mod`
are used thusly as infix operators. mod is a function name that,
brushing precedence under the rug, works rather like a prefix operator,
and you can put parentheses around the infix ones to make them prefix,
e.g., (+) 1 2
HTH.
Mark.
--
Functional programming vacancy at http://www.aetion.com/
In Haskell, infix operators are made up of the following symbols
ASCII...
!#$%&*+./<=>?@\^|-~
...plus some Unicode characters. You can also make "ordinary"
identifiers into infix ones by enclosing them in backquotes. And you
can apply the infix operators normally, by enclosing them in
parenthesis. Some examples...
Prelude> let a >:-| b = a + b
Prelude> 4 >:-| 5
9
Prelude> let x /\/\/ y = x + y
Prelude> 4 /\/\/ 5
9
Prelude> (+) 4 5
9
Prelude> div 20 5
4
Prelude> 20 `div` 5
4
Prelude> (/ 4) 20
5.0
Prelude> (4 /) 20
0.2
...See also section 2 of the Haskell Report...
http://www.haskell.org/onlinereport/
Greg Buchholz
Thanks!
rg
> Question 2: When you're reading code and you see "a b c" how are you
> supposed to know whether it means ((a b) c) or ((b a) c)?
Additionally to what has already been said, you should keep in mind
that all infix operators have priority and associativity. They are
declared by "infixr" (right associative), "infixl" (left associative),
"infix" (not associative).
The Prelude (i.e., the Haskell standard library) for example has the
following fixity declarations:
infixr 9 .
infixl 9 !!
infixr 8 ^, ^^, **
infixl 7 *, /, `quot`, `rem`, `div`, `mod`, :%, %
infixl 6 +, -
infixr 5 :
infixr 5 ++
infix 4 ==, /=, <, <=, >=, >, `elem`, `notElem`
infixr 3 &&
infixr 2 ||
infixl 1 >>, >>=
infixr 1 =<<
infixr 0 $, $!, `seq`
The means that "a + b * c" means the same as "(+) a ((*) b c)", as
one would expect. The operators (.) and ($) are composition and
application, i.e.
(f . g) x = f (g x))
f $ x = f x
and this allows some interesting idioms, for example "pipes" that
do processing in multiple steps (read from right to left):
doAll arg = doStep3 $ doStep2 $ doStep1 $ arg
or, with composition:
doAll = doStep3 . doStep2 . doStep1
One can also use infix operators as "syntactic sugar", to implement
a domain-specific sublanguage. There are for example some parser
libraries that make use of that idea, so one can write down grammar
rules in a form that reads a bit like a BNF. In Lisp, one would use
macros for that.
- Dirk
ML is a family of languages including Caml derivatives (Caml-light, OCaml,
F#, MetaOCaml, GCaml, JCaml, HashCaml, ...) and core-ML derivatives
(Standard ML, AliceML, Cambridge ML, Concurrent ML, ...).
OCaml is the most popular of all of those languages. I expect F# to become
the most popular over the next few years.
In OCaml, "f a b" means the curried function application "(f(a))(b)" and
there is no ambiguity.
If the "a" stands for an infix operator in OCaml then you know it is a
symbol or "word" composed of symbols. If the latter, it adopts the
precedence and associativity defined for the first symbol in the "word".
For example, a new operator @@:
# let ( @@ ) a b = Array.concat [a; b];;
val ( @@ ) : 'a array -> 'a array -> 'a array = <fun>
adopts the precedence and associativity (right) of the built-in "@" operator
(list append).
> But if
> there isn't, then let's constrain it to Haskell. That seems to be what
> all the cool kids are using nowadays.
Like ML, Haskell is a family of languages but Haskell is quite different:
pure and lazy with type classes.
--
Dr Jon D Harrop, Flying Frog Consultancy
Objective CAML for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists/index.html?usenet
> Question 2: When you're reading code and you see "a b c" how are you
> supposed to know whether it means ((a b) c) or ((b a) c)?
If b is a bare operator (not in parens),
a b c == (b) a c
e.g.
f . g == (.) f g
As Greg said, anything whose name is punctuation chars is an operator
rather than a function.
--
Dan
www.prairienet.org/~dsb
Why not just:
doAll arg = doStep3 doStep2 doStep1 arg
or even:
doAll = doStep3 doStep2 doStep1
?
rg
>> doAll arg = doStep3 $ doStep2 $ doStep1 $ arg
>>
>> or, with composition:
>>
>> doAll = doStep3 . doStep2 . doStep1
>
> Why not just:
>
> doAll arg = doStep3 doStep2 doStep1 arg
Because this means ((doStep3 doStep2) doStep1) arg, which is a way
(the standard way in many functional languages) to express a function
with multiple arguments, which is more common than applying several
one-argument functions in sequence.
--
__("< Marcin Kowalczyk
\__/ qrc...@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
> Ron Garret <rNOS...@flownet.com> writes:
>
> >> doAll arg = doStep3 $ doStep2 $ doStep1 $ arg
> >>
> >> or, with composition:
> >>
> >> doAll = doStep3 . doStep2 . doStep1
> >
> > Why not just:
> >
> > doAll arg = doStep3 doStep2 doStep1 arg
>
> Because this means ((doStep3 doStep2) doStep1) arg, which is a way
> (the standard way in many functional languages) to express a function
> with multiple arguments, which is more common than applying several
> one-argument functions in sequence.
Ah. So f $ g == (f g) == f g but f $ g $ h == (f (g h)) != f g h == ((f
g) h), right?
So what's the difference between f $ g $ h and f . g . h? (Are the
spaces required BTW? Can I write f$g$h and f.g.h?)
Is there a concise reference that explains all this?
rg
> Ah. So f $ g == (f g) == f g but f $ g $ h == (f (g h)) != f g h == ((f
> g) h), right?
Right.
> So what's the difference between f $ g $ h and f . g . h?
'f $ g $ h' and 'f . g $ h' are 'f (g h)', while 'f . g . h'
is '\x -> f (g (h x))'. And 'f $ g . h' is 'f (\x -> g (h x))'.
> (Are the spaces required BTW? Can I write f$g$h and f.g.h?)
Spaces are not required around operators. Almost.
The . symbol for function composition in Haskell was not the most
fortunate choice. 'Foo.bar' with a capitalized Foo means bar from
the module Foo, while 'Foo . bar' means Foo composed with bar
(when the . symbol was being chosen for function composition, Haskell
did not have the 'Foo.bar' syntax yet). Also, there have been some
experimental Haskell extensions where 'foo.bar' meant field bar of
record foo.
Haskell has only binary operators (except '-' for negation, and '~'
and '!' for certain rare constructs), which implies that the grammar
doesn't need two operators in a row, which means that a problem with
deciding where to split a sequence of operator-like characters doesn't
arise. Also, the characters ()[]{} can't appear in an operator name.
For these reasons, cases where a space is required before or after an
operator are very rare.
> Is there a concise reference that explains all this?
I don't remember a reference besides the Haskell 98 Report.
--
Dan
www.prairienet.org/~dsb
> Ron Garret <rNOS...@flownet.com> writes:
>
> > Ah. So f $ g == (f g) == f g but f $ g $ h == (f (g h)) != f g h == ((f
> > g) h), right?
>
> Right.
>
> > So what's the difference between f $ g $ h and f . g . h?
>
> 'f $ g $ h' and 'f . g $ h' are 'f (g h)', while 'f . g . h'
> is '\x -> f (g (h x))'. And 'f $ g . h' is 'f (\x -> g (h x))'.
Oh my. Now I understand why Haskell is so popular in academia. Tidbits
like that must make it easy to generate questions for the exam ;-)
One last question: how does juxtaposition fit into the scheme of things?
It's obviously left-associative but what is its precedence? And is that
defined in the prelude or just built in to the language?
rg
> One last question: how does juxtaposition fit into the scheme of things?
> It's obviously left-associative but what is its precedence?
Higher than operator application.
> And is that defined in the prelude or just built in to the language?
Built in.
> Ron Garret <rNOS...@flownet.com> writes:
>
> > One last question: how does juxtaposition fit into the scheme of things?
> > It's obviously left-associative but what is its precedence?
>
> Higher than operator application.
>
> > And is that defined in the prelude or just built in to the language?
>
> Built in.
Thanks!
rg