Haskell function declaration

I played with haskell, and I found out that if I write the following function in a code file:

f :: Int -> [a] -> a f idx str = last $ (take . succ) idx str 

then it works fine. Naturally, I realized that the code would look better without arguments.

 f :: Int -> [a] -> a f = last $ (take . succ) 

But this generates an error when I try to load it in gchi

 Couldn't match expected type `[a]' against inferred type `Int -> [a1] -> [a1]' In the second argument of `($)', namely `(take . succ)' In the expression: last $ (take . succ) In the definition of `f': f = last $ (take . succ) 

Failure, modules loaded: none.

I am a little confused about how this can happen ...

+6
haskell
source share
3 answers

This is what happens when you try to compile last with (take . succ)

 :t (.) (.) :: (b -> c) -> (a -> b) -> a -> c last :: [t] -> t ~ (b -> c) -- so b ~ [t] and c ~ t (take . succ) :: Int -> [t] -> [t] -- so a ~ int and b ~ [t] -> [t] 

Type b is defined as [t] from last , but it cannot match type b in (take . succ) , which is [t] -> [t]

+6
source share

You misunderstand the priority. It:

 f idx str = last $ (take . succ) idx str 

It is analyzed as follows:

 f idx str = last $ ( (take . succ) idx str ) 

Not (what do you think):

 f idx str = ( last $ (take . succ) ) idx str 

$ has an extremely low priority for any operator, and a function call has an extremely high level. . has the second highest, therefore (take . succ) binds it with arguments ( idx str ) before binding to last $ .

Also, the function (as it compiles) does not do what looks like what you want. It increments idx , then takes this character from the string. If this is what you want, why use succ when (+1) works? You have already limited the type to integers.

As written, your function is identical to the operator !! is just an array index function. Is this what you want? Or do you want a succ element at a given index? This can be done as follows:

 f :: Enum a => Int -> [a] -> a f idx str = succ $ str !! idx -- or f idx str = succ $ (!!) str idx -- or, only one argument f idx = succ . (!! idx) 

I am still working on a version with no written arguments. Perhaps it is more important to write working code ?;)

+10
source share
 f idx str = last $ (take . succ) idx str -- applying definition of ($) f idx str = last ((take . succ) idx str) -- adding parentheses for clarity f idx str = last (((take . succ) idx) str) -- using definition of (.) f idx str = (last . (take . succ) idx) str -- η-conversion f idx = last . (take . succ) idx -- infix to prefix notation f idx = (.) last ((take . succ) idx) -- ading parentheses for clarity f idx = ((.) last) ((take . succ) idx) -- using definition of (.) f idx = ((.) last . (take . succ)) idx -- η-conversion f = (.) last . (take . succ) -- remove parentheses: (.) is right-associative f = (.) last . take . succ 
+5
source share

All Articles