1
votes

this line of code in Haskell produces an error on compilation:

lineStat :: String -> [String]
lineStat xs =  zipWith (\n line -> show n ++ " " ++ show $ length line) [1..] $ lines xs

Error: Couldn't match expected type Int -> String with actual type [Char] The first argument of ($) takes one argument,but its type [Char] has none

However this line of code works:

lineStat xs =  zipWith (\n line -> show n ++ " " ++ show (length line)) [1..] $ lines xs

Why?

2

2 Answers

4
votes

It's a precedence issue.

show n ++ " " ++ show $ length line

means

(show n ++ " " ++ show) (length line)

which makes no sense since show is not a string. It does not mean

show n ++ " " ++ (show (length line))

To get the wanted one, you need parentheses. Use one of these:

zipWith (\n line -> show n ++ " " ++ show (length line)) [1..] $ lines xs
-- or
zipWith (\n line -> show n ++ " " ++ (show $ length line)) [1..] $ lines xs

I'd prefer the former since it's simpler.

2
votes

Your problem boils down to:

*Main> let line = "abc"
*Main> " " ++ show (length line)
" 3"
*Main> " " ++ show $length line
<interactive>:9:1: error:
    • Couldn't match expected type ‘Int -> t’ with actual type ‘[Char]’

The root cause for this is that $ has lower precedence than ++:

*Main> :info (++)
...
infixr 5 ++
*Main> :info ($)
...
infixr 0 $

as defined in the Haskell Report

Therefore, you need parentheses around show $ length line.