
Dear Haskell supporters, I have a some question about the definitions in haskell. 1. What is the use of making definitions compared to having no definitions? Is it just like a comment for documation or does it really make a difference in compiling the code? 2. What does the arrow(->) mean in such a definition? Is it a binary operation as *, +, -, <,>,= or is it something else? For example there is sumWithL :: [Int] -> Int -> Int Does this mean in other words [Int]+Int=Int 1. Why do we use clinches in such definitions. I concluded you need clinches if a function is not associative such as (a-b)+c . (Int->Int)->Int->Int But also if a higher order function needs more than one argument. (a->b)->c . Can you please explain it ? Thank you Kind regards. Gesendet von Mailhttps://go.microsoft.com/fwlink/?LinkId=550986 für Windows 10

Hello Steafan, On Wed, Aug 15, 2018 at 09:06:40PM +0000, Stefan Chacko wrote:
1. What is the use of making definitions compared to having no definitions? Is it just like a comment for documation or does it really make a difference in compiling the code?
Writing signatures is always useful: - to prototype (and let the compiler complain about wrong types) - to restrict a function to some types only, e.g. intHead :: [Int] -> Int intHead is = head is - to have an immediate, clear, verifiable documentation near the functions
2. What does the arrow(->) mean in such a definition? [...] For example there is sumWithL :: [Int] -> Int -> Int
`[Int] -> Int -> Int` can be (with great approximation) be read "this function takes two arguments, `[Int]` and `Int`, to return an `Int`. More precisely, if you provide `[Int]` you'll get back a function that takes an Int to return one Int (Int -> Int), and if you (finally) pass an Int to that, you receive the final result.
1. Why do we use clinches in such definitions. I concluded you need clinches if a function is not associative
(->) (called `function application`) associates to the right, so sumWithL :: [Int] -> Int -> Int is equal to sumWithL :: [Int] -> (Int -> Int) If you want a function that takes a function `[Int] -> Int` to return an Int you got to put parentheses: sumWithL :: ([Int] -> Int) -> Int Hope it was clear! -F p.s. haskell@haskell.org is for announcements only, so I am removing it from cc.

Il 15/08/2018 23:06, Stefan Chacko ha scritto:
3. Why do we use clinches in such definitions. I concluded you need clinches if a function is not associative
such as (a-b)+c . (Int->Int)->Int->Int
But also if a higher order function needs more than one argument. (a->b)->c .
Can you please explain it ?
funXYZ :: Int -> Int -> Int -> Int funXYZ x y z = (x - y) + z if you rewrite in pure lamdda-calculus, without any syntax-sugars it became fun_XYZ :: (Int -> (Int -> (Int -> Int))) fun_XYZ = \x -> \y -> \z -> (x - y) + z so fun_XYZ is a function `\x -> ...` that accepts x, and return a function, that accepts a parameter y, and return a function, etc... You can also rewrite as: funX_YZ :: Int -> (Int -> (Int -> Int)) funX_YZ x = \y -> \z -> (x - y) + z or funXY_Z :: Int -> Int -> (Int -> Int) funXY_Z x y = \z -> (x - y) + z and finally again in the original funXYZ_ :: Int -> Int -> Int -> Int funXYZ_ x y z = (x - y) + z I used different names only for clarity, but they are the same exact function in Haskell. In lambda-calculus the form \x y z -> (x - y) + z is syntax sugar for \x -> \y -> \z -> (x - y) + z On the contrary (as Francesco said) (Int -> Int) -> Int -> Int is a completely different type respect Int -> Int -> Int -> Int In particular a function like gHX :: (Int -> Int) -> Int -> Int gHX h x = h x has 2 parameters, and not 3. The first parameter has type (Int -> Int), the second type Int, and then it returns an Int. Equivalent forms are: g_HX :: (Int -> (Int -> Int)) g_HX = \h -> \x -> h x gH_X :: (Int -> Int) -> (Int -> Int) gH_X h = \x -> h x gHX :: (Int -> Int) -> Int -> Int gHX_ h x = h x IMHO it is similar to logic: intuitively it seems easy and natural, but if you reflect too much, it is not easy anymore... but after you internalize some rules, it is easy and natural again. Regards, Massimo

Hmm, very interesting question, really: what is the "->" in functions signatures: type-level operator or syntax only? 16.08.2018 01:20, Massimo Zaniboni wrote:
Il 15/08/2018 23:06, Stefan Chacko ha scritto:
3. Why do we use clinches in such definitions. I concluded you need clinches if a function is not associative such as (a-b)+c . (Int->Int)->Int->Int
But also if a higher order function needs more than one argument. (a->b)->c .
Can you please explain it ?
funXYZ :: Int -> Int -> Int -> Int funXYZ x y z = (x - y) + z
if you rewrite in pure lamdda-calculus, without any syntax-sugars it became
fun_XYZ :: (Int -> (Int -> (Int -> Int))) fun_XYZ = \x -> \y -> \z -> (x - y) + z
so fun_XYZ is a function `\x -> ...` that accepts x, and return a function, that accepts a parameter y, and return a function, etc...
You can also rewrite as:
funX_YZ :: Int -> (Int -> (Int -> Int)) funX_YZ x = \y -> \z -> (x - y) + z
or
funXY_Z :: Int -> Int -> (Int -> Int) funXY_Z x y = \z -> (x - y) + z
and finally again in the original
funXYZ_ :: Int -> Int -> Int -> Int funXYZ_ x y z = (x - y) + z
I used different names only for clarity, but they are the same exact function in Haskell.
In lambda-calculus the form
\x y z -> (x - y) + z
is syntax sugar for
\x -> \y -> \z -> (x - y) + z
On the contrary (as Francesco said)
(Int -> Int) -> Int -> Int
is a completely different type respect
Int -> Int -> Int -> Int
In particular a function like
gHX :: (Int -> Int) -> Int -> Int gHX h x = h x
has 2 parameters, and not 3. The first parameter has type (Int -> Int), the second type Int, and then it returns an Int. Equivalent forms are:
g_HX :: (Int -> (Int -> Int)) g_HX = \h -> \x -> h x
gH_X :: (Int -> Int) -> (Int -> Int) gH_X h = \x -> h x
gHX :: (Int -> Int) -> Int -> Int gHX_ h x = h x
IMHO it is similar to logic: intuitively it seems easy and natural, but if you reflect too much, it is not easy anymore... but after you internalize some rules, it is easy and natural again.
Regards, Massimo _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

It is a type level operator. You can parameterize things by it:
type Foo f = f Int String
foo :: Foo (->)
foo = show
-- Write instances for it:
class Profunctor p where
dimap :: (a -> b) -> (c -> d) -> p b c -> p a d
instance Profunctor (->) where
dimap ab cd bc = cd . bc . ab
-- Define aliases for it:
type Func a b = a -> b
map :: Func a b -> [a] -> [b]
-- or even,
map :: Func a b -> Func [a] [b]
-- Use it prefix
dropWhile :: ((->) a Bool) -> [a] -> [a]
-- Partially apply it:
instance MonadReader r ((->) r) where
ask = id
Matt Parsons
On Wed, Aug 15, 2018 at 10:53 PM, Paul
Hmm, very interesting question, really: what is the "->" in functions signatures: type-level operator or syntax only?
16.08.2018 01:20, Massimo Zaniboni wrote:
Il 15/08/2018 23:06, Stefan Chacko ha scritto:
3. Why do we use clinches in such definitions. I concluded you need
clinches if a function is not associative such as (a-b)+c . (Int->Int)->Int->Int
But also if a higher order function needs more than one argument. (a->b)->c .
Can you please explain it ?
funXYZ :: Int -> Int -> Int -> Int funXYZ x y z = (x - y) + z
if you rewrite in pure lamdda-calculus, without any syntax-sugars it became
fun_XYZ :: (Int -> (Int -> (Int -> Int))) fun_XYZ = \x -> \y -> \z -> (x - y) + z
so fun_XYZ is a function `\x -> ...` that accepts x, and return a function, that accepts a parameter y, and return a function, etc...
You can also rewrite as:
funX_YZ :: Int -> (Int -> (Int -> Int)) funX_YZ x = \y -> \z -> (x - y) + z
or
funXY_Z :: Int -> Int -> (Int -> Int) funXY_Z x y = \z -> (x - y) + z
and finally again in the original
funXYZ_ :: Int -> Int -> Int -> Int funXYZ_ x y z = (x - y) + z
I used different names only for clarity, but they are the same exact function in Haskell.
In lambda-calculus the form
\x y z -> (x - y) + z
is syntax sugar for
\x -> \y -> \z -> (x - y) + z
On the contrary (as Francesco said)
(Int -> Int) -> Int -> Int
is a completely different type respect
Int -> Int -> Int -> Int
In particular a function like
gHX :: (Int -> Int) -> Int -> Int gHX h x = h x
has 2 parameters, and not 3. The first parameter has type (Int -> Int), the second type Int, and then it returns an Int. Equivalent forms are:
g_HX :: (Int -> (Int -> Int)) g_HX = \h -> \x -> h x
gH_X :: (Int -> Int) -> (Int -> Int) gH_X h = \x -> h x
gHX :: (Int -> Int) -> Int -> Int gHX_ h x = h x
IMHO it is similar to logic: intuitively it seems easy and natural, but if you reflect too much, it is not easy anymore... but after you internalize some rules, it is easy and natural again.
Regards, Massimo _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
participants (5)
-
Francesco Ariis
-
Massimo Zaniboni
-
Matt
-
Paul
-
Stefan Chacko