Reputation: 85
I want to check if a string given by the user is only composed from characters of another string previously given as program arguments
I have search every where for doing this in haskell but I didn't found anything (found answer for other language but not haskell) I know how to do this in python or in C but this is my first haskell program
Here is what I have so far :
I'm calling the function + setup of the string to check
myCheck first second = do
-- some stuff
let alpha = "01" -- normally this is given with argument by the user but just for simplicity let's do it that way (it could also be alpha = "aziuefè!çè")
suite <- getLine
if isValid suite alpha
then putStr "OK\n"
else exit
-- some other stuff
Now the Is valid function the isValid "" alpha = True is important because I need to handle that elsewhere later in the code
isValid :: String -> String -> Bool
isValid "" alpha = True
isValid xs alpha =
case dropWhile (isAlphabet xs alpha) of
"" -> True
('.':ys) -> all (isAlphabet ys alpha)
_ -> False
And the isAlphabet function
isAlphabet :: Char -> String -> Bool
isAlphabet xs alpha = xs `elem` alpha
But (and I'm starting to get used to while using haskell)
/Users/mgial/tech2/FUN_deBruijn_2017/app/Main.hs:29:19: error:
• Couldn't match expected type ‘a0 -> Bool’ with actual type ‘Bool’
• Possible cause: ‘isAlphabet’ is applied to too many arguments
In the first argument of ‘dropWhile’, namely
‘(isAlphabet xs alpha)’
In the expression: dropWhile (isAlphabet xs alpha)
In the expression:
case dropWhile (isAlphabet xs alpha) of
"" -> True
('.' : ys) -> all (isAlphabet ys alpha)
_ -> False
|
29 | case dropWhile (isAlphabet xs alpha) of
| ^^^^^^^^^^^^^^^^^^^
/Users/mgial/tech2/FUN_deBruijn_2017/app/Main.hs:29:30: error:
• Couldn't match type ‘[Char]’ with ‘Char’
Expected type: Char
Actual type: String
• In the first argument of ‘isAlphabet’, namely ‘xs’
In the first argument of ‘dropWhile’, namely
‘(isAlphabet xs alpha)’
In the expression: dropWhile (isAlphabet xs alpha)
|
29 | case dropWhile (isAlphabet xs alpha) of
| ^^
/Users/mgial/tech2/FUN_deBruijn_2017/app/Main.hs:30:5: error:
• Couldn't match expected type ‘[a0] -> [a0]’
with actual type ‘[Char]’
• In the pattern: ""
In a case alternative: "" -> True
In the expression:
case dropWhile (isAlphabet xs alpha) of
"" -> True
('.' : ys) -> all (isAlphabet ys alpha)
_ -> False
|
30 | "" -> True
| ^^
/Users/mgial/tech2/FUN_deBruijn_2017/app/Main.hs:31:6: error:
• Couldn't match expected type ‘[a0] -> [a0]’
with actual type ‘[Char]’
• In the pattern: '.' : ys
In a case alternative: ('.' : ys) -> all (isAlphabet ys alpha)
In the expression:
case dropWhile (isAlphabet xs alpha) of
"" -> True
('.' : ys) -> all (isAlphabet ys alpha)
_ -> False
|
31 | ('.':ys) -> all (isAlphabet ys alpha)
| ^^^^^^
/Users/mgial/tech2/FUN_deBruijn_2017/app/Main.hs:31:17: error:
• Couldn't match expected type ‘Bool’
with actual type ‘t0 a1 -> Bool’
• Probable cause: ‘all’ is applied to too few arguments
In the expression: all (isAlphabet ys alpha)
In a case alternative: ('.' : ys) -> all (isAlphabet ys alpha)
In the expression:
case dropWhile (isAlphabet xs alpha) of
"" -> True
('.' : ys) -> all (isAlphabet ys alpha)
_ -> False
|
31 | ('.':ys) -> all (isAlphabet ys alpha)
| ^^^^^^^^^^^^^^^^^^^^^^^^^
/Users/mgial/tech2/FUN_deBruijn_2017/app/Main.hs:31:22: error:
• Couldn't match expected type ‘a1 -> Bool’ with actual type ‘Bool’
• Possible cause: ‘isAlphabet’ is applied to too many arguments
In the first argument of ‘all’, namely ‘(isAlphabet ys alpha)’
In the expression: all (isAlphabet ys alpha)
In a case alternative: ('.' : ys) -> all (isAlphabet ys alpha)
|
31 | ('.':ys) -> all (isAlphabet ys alpha)
| ^^^^^^^^^^^^^^^^^^^
/Users/mgial/tech2/FUN_deBruijn_2017/app/Main.hs:31:33: error:
• Couldn't match expected type ‘Char’ with actual type ‘[Char]’
• In the first argument of ‘isAlphabet’, namely ‘ys’
In the first argument of ‘all’, namely ‘(isAlphabet ys alpha)’
In the expression: all (isAlphabet ys alpha)
|
31 | ('.':ys) -> all (isAlphabet ys alpha)
| ^^
This specific function isn't homework but part of a bigger project that is Thank you, really hope I didn't miss any previous questions already answered
Edit suggested by answer :
Removed isAlphabet (this function wasn't making any sense, since it was only calling elem)
isValid :: String -> String -> Bool
isValid "" alpha = True
isValid xs alpha =
case dropWhile (xs `elem` alpha) of
"" -> True
('.':ys) -> all (`elem` alpha) ys
_ -> False
compile errors :
/Users/mgial/tech2/FUN_deBruijn_2017/app/Main.hs:26:19: error:
• Couldn't match expected type ‘a0 -> Bool’ with actual type ‘Bool’
• Possible cause: ‘elem’ is applied to too many arguments
In the first argument of ‘dropWhile’, namely ‘(xs `elem` alpha)’
In the expression: dropWhile (xs `elem` alpha)
In the expression:
case dropWhile (xs `elem` alpha) of
"" -> True
('.' : ys) -> all (`elem` alpha) ys
_ -> False
|
26 | case dropWhile (xs `elem` alpha) of
| ^^^^^^^^^^^^^^^
/Users/mgial/tech2/FUN_deBruijn_2017/app/Main.hs:26:29: error:
• Couldn't match type ‘Char’ with ‘[Char]’
Expected type: [String]
Actual type: String
• In the second argument of ‘elem’, namely ‘alpha’
In the first argument of ‘dropWhile’, namely ‘(xs `elem` alpha)’
In the expression: dropWhile (xs `elem` alpha)
|
26 | case dropWhile (xs `elem` alpha) of
| ^^^^^
/Users/mgial/tech2/FUN_deBruijn_2017/app/Main.hs:27:5: error:
• Couldn't match expected type ‘[a0] -> [a0]’
with actual type ‘[Char]’
• In the pattern: ""
In a case alternative: "" -> True
In the expression:
case dropWhile (xs `elem` alpha) of
"" -> True
('.' : ys) -> all (`elem` alpha) ys
_ -> False
|
27 | "" -> True
| ^^
/Users/mgial/tech2/FUN_deBruijn_2017/app/Main.hs:28:6: error:
• Couldn't match expected type ‘[a0] -> [a0]’
with actual type ‘[Char]’
• In the pattern: '.' : ys
In a case alternative: ('.' : ys) -> all (`elem` alpha) ys
In the expression:
case dropWhile (xs `elem` alpha) of
"" -> True
('.' : ys) -> all (`elem` alpha) ys
_ -> False
|
28 | ('.':ys) -> all (`elem` alpha) ys
| ^^^^^^
Final edit :
isValid :: String -> String -> Bool
isValid "" alpha = True
isValid xs alpha =
case dropWhile (`elem` alpha) xs of
"" -> True
('.':ys) -> all (`elem` alpha) ys
_ -> False
Upvotes: 1
Views: 286
Reputation: 120741
With all (isAlphabet ys alpha)
, you try to first apply isAlphabet
to the entire string ys
and the alphabet, and then somehow pull the result of that through all
. But, the types don't support this:
isAlphabet :: Char -> String -> Bool
│ │ │
ys :: String │ │
alpha :: String │
all :: (a->Bool) -> [a] -> Bool
What you instead want to do is use all
to apply isAlphabet
to each character individually. That's what it's there for.
... all (\c -> isAlphabet c alpha) ys ...
Note that if you'd defined the isAlphabet
function which swapped arguments (which would be the more natural order) then you could shorten (eta-reduce) this to
isAlphabet :: String -> Char -> Bool
... all (isAlphabet alpha) ys ...
Alternatively you can use an operator section to directly apply the second argument. In fact I wouldn't bother defining isAlphabet
in the first place, because it's actually an exact synonym for elem
. Just write
... all (`elem` alpha) ys ...
all :: (a->Bool) -> [a] -> Bool
│ │
(`elem`alpha) :: Char->Bool │
ys :: String
Upvotes: 4