Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Post History

71%
+3 −0
Q&A How to use function composition for applying a function to first elements of a list?

The quick fix is: map (subtract 1) . take n $ l When I put your function in my own Haskell compiler, I get: Possible cause: ‘take’ is applied to too many arguments Remember that in Haskell,...

posted 1y ago by FractionalRadix‭  ·  edited 1y ago by FractionalRadix‭

Answer
#5: Post edited by user avatar FractionalRadix‭ · 2023-07-13T19:57:17Z (over 1 year ago)
  • The quick fix is:
  • `map (subtract 1) . take n $ l`
  • When I put your function in my own Haskell compiler, I get:
  • > Possible cause: ‘take’ is applied to too many arguments
  • Remember that in Haskell, we don't have functions with multiple parameters. We have functions with a single parameter, that return either values or new functions. (That, in turn, only take a single parameter).
  • <del>
  • `map (subtract 1) . take n l` is read by Haskell as `map (subtract 1) .take n`. This is a complete function that takes a list of `Num` and returns a list of `Num`. Then it reads an `l` and it doesn't know what to do with it.
  • </del>
  • `map (subtract 1) . take n l` is read by Haskell as `(map (subtract 1)) . (take n l)` .
  • * The first part is a function that maps a list of numbers to a list of numbers. It has type `(Num b) => [b] -> [b]`.
  • * The second part is a function that maps an integer to a function that takes a list and returns a list. It has type `Int -> [a] -> [a]`.
  • So it tries to do function composition, where the first function is of type `([b] -> [b])`, and the second of type `(Int -> [a] -> [a])`. That's not compatible.
  • We can make it work by writing it as `(map (subtract 1)) . take n)( l )`, or the shorthand function `map (subtract 1)) . take n $ l`. Now we have a function that subtracts 1 from every element in a list, and takes the first n elements of the result. This function then gets our list as argument.
  • ---
  • In your comment, you pointed out that you also tried:
  • dec_first = map (subtract 1) . take
  • This gave you a different error message:
  • > Probable cause: `take' is applied to too few arguments
  • This time, we have the opposite situation. The function `map (subtract 1)` is a neat function that takes a list of `Num` and returns a list of `Num`: it is of type `(Num a) => [a] -> [a]`.
  • You then try to apply this to `take`, whose type is `Int -> [a] -> [a]`. It's a function that takes an integer, to yield a function that takes a list and yields a list. But... Haskell doesn't see any integers!
  • We can fix this by giving it the Integer it wants:
  • dec_first n = map (subtract 1) . take n
  • If you're using GHCi, you can put `:t` in front of a function to see its type. For example:
  • > ghci> :t map (subtract 1)
  • > map (subtract 1) :: Num b => [b] -> [b]
  • This can be very helpful to see if the type of your function is what you expected it to be, and to see if it matches the functions you're feeding it.
  • The quick fix is:
  • `map (subtract 1) . take n $ l`
  • When I put your function in my own Haskell compiler, I get:
  • > Possible cause: ‘take’ is applied to too many arguments
  • Remember that in Haskell, we don't have functions with multiple parameters. We have functions with a single parameter, that return either values or new functions. (That, in turn, only take a single parameter).
  • `map (subtract 1) . take n l` is read by Haskell as `(map (subtract 1)) . (take n l)` .
  • * The first part is a function that maps a list of numbers to a list of numbers. It has type `(Num b) => [b] -> [b]`.
  • * The second part is a function that maps an integer to a function that takes a list and returns a list. It has type `Int -> [a] -> [a]`.
  • So it tries to do function composition, where the first function is of type `([b] -> [b])`, and the second of type `(Int -> [a] -> [a])`. That's not compatible.
  • We can make it work by writing it as `(map (subtract 1)) . take n)( l )`, or the shorthand function `map (subtract 1)) . take n $ l`. Now we have a function that subtracts 1 from every element in a list, and takes the first n elements of the result. This function then gets our list as argument.
  • ---
  • In your comment, you pointed out that you also tried:
  • dec_first = map (subtract 1) . take
  • This gave you a different error message:
  • > Probable cause: `take' is applied to too few arguments
  • This time, we have the opposite situation. The function `map (subtract 1)` is a neat function that takes a list of `Num` and returns a list of `Num`: it is of type `(Num a) => [a] -> [a]`.
  • You then try to apply this to `take`, whose type is `Int -> [a] -> [a]`. It's a function that takes an integer, to yield a function that takes a list and yields a list. But... Haskell doesn't see any integers!
  • We can fix this by giving it the Integer it wants:
  • dec_first n = map (subtract 1) . take n
  • If you're using GHCi, you can put `:t` in front of a function to see its type. For example:
  • > ghci> :t map (subtract 1)
  • > map (subtract 1) :: Num b => [b] -> [b]
  • This can be very helpful to see if the type of your function is what you expected it to be, and to see if it matches the functions you're feeding it.
#4: Post edited by user avatar FractionalRadix‭ · 2023-07-13T19:56:57Z (over 1 year ago)
Updated answer in the light of cafce25's comment.
  • The quick fix is:
  • `map (subtract 1) . take n $ l`
  • When I put your function in my own Haskell compiler, I get:
  • > Possible cause: ‘take’ is applied to too many arguments
  • Remember that in Haskell, we don't have functions with multiple parameters. We have functions with a single parameter, that return either values or new functions. (That, in turn, only take a single parameter).
  • `map (subtract 1) . take n l` is read by Haskell as `map (subtract 1) .take n`. This is a complete function that takes a list of `Num` and returns a list of `Num`. Then it reads an `l` and it doesn't know what to do with it.
  • In your comment, you pointed out that you also tried:
  • dec_first = map (subtract 1) . take
  • This gave you a different error message:
  • > Probable cause: `take' is applied to too few arguments
  • This time, we have the opposite situation. The function `map (subtract 1)` is a neat function that takes a list of `Num` and returns a list of `Num`: it is of type `(Num a) => [a] -> [a]`.
  • You then try to apply this to `take`, whose type is `Int -> [a] -> [a]`. It's a function that takes an integer, to yield a function that takes a list and yields a list. But... Haskell doesn't see any integers!
  • We can fix this by giving it the Integer it wants:
  • dec_first n = map (subtract 1) . take n
  • If you're using GHCi, you can put `:t` in front of a function to see its type. For example:
  • > ghci> :t map (subtract 1)
  • > map (subtract 1) :: Num b => [b] -> [b]
  • This can be very helpful to see if the type of your function is what you expected it to be, and to see if it matches the functions you're feeding it.
  • The quick fix is:
  • `map (subtract 1) . take n $ l`
  • When I put your function in my own Haskell compiler, I get:
  • > Possible cause: ‘take’ is applied to too many arguments
  • Remember that in Haskell, we don't have functions with multiple parameters. We have functions with a single parameter, that return either values or new functions. (That, in turn, only take a single parameter).
  • <del>
  • `map (subtract 1) . take n l` is read by Haskell as `map (subtract 1) .take n`. This is a complete function that takes a list of `Num` and returns a list of `Num`. Then it reads an `l` and it doesn't know what to do with it.
  • </del>
  • `map (subtract 1) . take n l` is read by Haskell as `(map (subtract 1)) . (take n l)` .
  • * The first part is a function that maps a list of numbers to a list of numbers. It has type `(Num b) => [b] -> [b]`.
  • * The second part is a function that maps an integer to a function that takes a list and returns a list. It has type `Int -> [a] -> [a]`.
  • So it tries to do function composition, where the first function is of type `([b] -> [b])`, and the second of type `(Int -> [a] -> [a])`. That's not compatible.
  • We can make it work by writing it as `(map (subtract 1)) . take n)( l )`, or the shorthand function `map (subtract 1)) . take n $ l`. Now we have a function that subtracts 1 from every element in a list, and takes the first n elements of the result. This function then gets our list as argument.
  • ---
  • In your comment, you pointed out that you also tried:
  • dec_first = map (subtract 1) . take
  • This gave you a different error message:
  • > Probable cause: `take' is applied to too few arguments
  • This time, we have the opposite situation. The function `map (subtract 1)` is a neat function that takes a list of `Num` and returns a list of `Num`: it is of type `(Num a) => [a] -> [a]`.
  • You then try to apply this to `take`, whose type is `Int -> [a] -> [a]`. It's a function that takes an integer, to yield a function that takes a list and yields a list. But... Haskell doesn't see any integers!
  • We can fix this by giving it the Integer it wants:
  • dec_first n = map (subtract 1) . take n
  • If you're using GHCi, you can put `:t` in front of a function to see its type. For example:
  • > ghci> :t map (subtract 1)
  • > map (subtract 1) :: Num b => [b] -> [b]
  • This can be very helpful to see if the type of your function is what you expected it to be, and to see if it matches the functions you're feeding it.
#3: Post edited by user avatar FractionalRadix‭ · 2023-07-13T17:02:16Z (over 1 year ago)
  • The quick fix is:
  • `map (subtract 1) . take 3 $ l`
  • (I don't have a Haskell compiler on this machine, but putting `map (subtract 1) . take 3 $ [1..5]` in tryhaskell.org gives [0,1,2] as expected).
  • The error message I get for `map (subtract 1) . take 3 [1..5]` reads:
  • > Possible cause: ‘take’ is applied to too many arguments
  • When the Haskell compiler receives your `map (subtract 1) . take n l` , it sees `map (subtract 1) . take n` and then an extra `l` that it doesn't know what to do with.
  • By adding the `$`, your `map (subtract 1) . take n` becomes a function to be applied to a list.
  • The quick fix is:
  • `map (subtract 1) . take n $ l`
  • When I put your function in my own Haskell compiler, I get:
  • > Possible cause: ‘take’ is applied to too many arguments
  • Remember that in Haskell, we don't have functions with multiple parameters. We have functions with a single parameter, that return either values or new functions. (That, in turn, only take a single parameter).
  • `map (subtract 1) . take n l` is read by Haskell as `map (subtract 1) .take n`. This is a complete function that takes a list of `Num` and returns a list of `Num`. Then it reads an `l` and it doesn't know what to do with it.
  • In your comment, you pointed out that you also tried:
  • dec_first = map (subtract 1) . take
  • This gave you a different error message:
  • > Probable cause: `take' is applied to too few arguments
  • This time, we have the opposite situation. The function `map (subtract 1)` is a neat function that takes a list of `Num` and returns a list of `Num`: it is of type `(Num a) => [a] -> [a]`.
  • You then try to apply this to `take`, whose type is `Int -> [a] -> [a]`. It's a function that takes an integer, to yield a function that takes a list and yields a list. But... Haskell doesn't see any integers!
  • We can fix this by giving it the Integer it wants:
  • dec_first n = map (subtract 1) . take n
  • If you're using GHCi, you can put `:t` in front of a function to see its type. For example:
  • > ghci> :t map (subtract 1)
  • > map (subtract 1) :: Num b => [b] -> [b]
  • This can be very helpful to see if the type of your function is what you expected it to be, and to see if it matches the functions you're feeding it.
#2: Post edited by user avatar FractionalRadix‭ · 2023-07-13T15:37:14Z (over 1 year ago)
  • The quick fix is:
  • `map (subtract 1) . take 3 $ l`
  • (I don't have a Haskell compiler on this machine, but putting `map (subtract 1) . take 3 $ [1..5]` in tryhaskell.org gives [0,1,2] as expected).
  • The error message I get for `map (subtract 1) . take 3 [1..5]` reads:
  • > Possible cause: ‘take’ is applied to too many arguments
  • When the Haskell compiler receives your `map (subtract 1) . take n l` , it sees `map (subtract 1) . take n` and then an extra `l` that it doesn't know what to do with.
  • By adding the `$`, your ``map (subtract 1) . take n` becomes a function to be applied to a list.
  • The quick fix is:
  • `map (subtract 1) . take 3 $ l`
  • (I don't have a Haskell compiler on this machine, but putting `map (subtract 1) . take 3 $ [1..5]` in tryhaskell.org gives [0,1,2] as expected).
  • The error message I get for `map (subtract 1) . take 3 [1..5]` reads:
  • > Possible cause: ‘take’ is applied to too many arguments
  • When the Haskell compiler receives your `map (subtract 1) . take n l` , it sees `map (subtract 1) . take n` and then an extra `l` that it doesn't know what to do with.
  • By adding the `$`, your `map (subtract 1) . take n` becomes a function to be applied to a list.
#1: Initial revision by user avatar FractionalRadix‭ · 2023-07-13T15:36:31Z (over 1 year ago)
The quick fix is:

`map (subtract 1) . take 3 $ l`

(I don't have a Haskell compiler on this machine, but putting `map (subtract 1) . take 3 $ [1..5]` in tryhaskell.org gives [0,1,2] as expected).

The error message I get for `map (subtract 1) . take 3 [1..5]` reads: 

> Possible cause: ‘take’ is applied to too many arguments

When the Haskell compiler receives your `map (subtract 1) . take n l` , it sees `map (subtract 1) . take n` and then an extra `l` that it doesn't know what to do with.  
By adding the `$`, your ``map (subtract 1) . take n` becomes a function to be applied to a list.