Reputation: 897
I have a function:
setDisplays :: Char -> [String] -> IO()
setDisplays mode dIds
| mode == 'l' = chngDispl (head dIds)
| mode == 'e' = chngDispl (tail dIds)
where
chngDispl on = mapM_ (\id -> callProcess "xrandr" ["--output", id, "--auto"]) on
that gets a list of strings with the ids of Displays provided by xrandr which looks like this ["eDP1", "HDMI1"]
. The list is passed to setDisplays
by binding an IO ()
:
getDisplays >>= setDisplays 'e'
Now, I get the following error message: parser.hs:50:37:
Couldn't match type ‘Char’ with ‘[Char]’
Expected type: [[String]]
Actual type: [String]
In the first argument of ‘head’, namely ‘dIds’
In the first argument of ‘chngDispl’, namely ‘(head dIds)’
Failed, modules loaded: none.
which I don't get. Even ghc-mod is telling me that the name dIds when it is first mentioned identifies [String]
and when I typecheck with ghc-mod in the function call it identifies [[[Char]]]
. What is happening here?
Upvotes: 1
Views: 96
Reputation: 7393
If dIds
is a [String]
, then the result of head
will be a String
, but chngDispl
expects a [String]
. That’s why the compiler thinks that the argument of head
should be a [[String]]
.
Wrap head dIds
in a list and the error should go away.
You should generally avoid head
and use pattern matching instead. You can rewrite your function like this:
setDisplays :: Char -> [String] -> IO()
setDisplays mode (id:ids)
| mode == 'l' = chngDispl [id]
| mode == 'e' = chngDispl ids
where
chngDispl on = mapM_ (\id -> callProcess "xrandr" ["--output", id, "--auto"]) on
Note that this will fail if the list is empty (but so will head
), you should handle that case as well.
Upvotes: 4
Reputation: 4596
You are using head
on dIds
and expect that to be a [String]
. Thus, type inference tells us, that dIds to be used that way should be of type [[String]]
.
Also, you are using tail
on dIds
one line below. That doesn't type match.
Upvotes: 4