I try to write a program for an exercise. It should read a String and return an empty list if it could parse the String according to a given grammar. In case the String is not in valid grammar it should return "Nothing". Like here:
>prog "c+c*c$"
Just""
>prog "c+c-c$"
Nothing
I wrote the following functions they are loaded and compile in GHCI, but when i run prog with any argument i get the following exception: *** Exception: Maybe.fromJust: Nothing
I suppose i access or pass a Maybe String in a wrong way, but not sure where. Any help regarding the right handling of Maybe structures are welcome.
Here is my code:
import Data.Maybe
match :: Char -> Maybe String -> Maybe String
match x input
| (isNothing input == False) && (x == head (fromJust(input))) = Just (tail (fromJust(input)))
| otherwise = Nothing
prog :: String -> Maybe String
prog x = match '$' (expr (Just (x)))
expr :: Maybe String -> Maybe String
expr x = ttail (term x)
term :: Maybe String -> Maybe String
term x = ftail (factor x)
ttail :: Maybe String -> Maybe String
ttail x
| fromJust(x) == [] = Just []
| otherwise = ttail (term (match '+' x))
factor :: Maybe String -> Maybe String
factor x = match 'c' x
ftail :: Maybe String -> Maybe String
ftail x
| fromJust(x) == [] = Just []
| otherwise = ftail ( factor ( match '*' x))
There are several antipatterns in the OP's code. I'll only discuss this snippet.
match :: Char -> Maybe String -> Maybe String
match x input
| (isNothing input == False) && (x == head (fromJust(input))) = Just (tail (fromJust(input)))
| otherwise = Nothing
Using isNothing, fromJust is an antipattern, since the latter is a partial function which crashes the program when fed with Nothing. The programmer has to be careful to always check isJust beforehand, which is easy to forget. It is much simpler to forget about these functions completely and rely on pattern matching instead (see below).
.. == False should be rewritten as not ..
not (isNothing ..) should be isJust .. (but again, pattern matching makes this pointless)
head,tail,!! are partial functions too, and they should be replaced with pattern matching, when possible. Above, head is potentially called on [], so we would need to check it beforehand. Pattern matching avoids the need.
Instead of .. == [] one can use null .. (or, better, pattern matching).
Never write f(x) for a function call, the parentheses have no purpose there.
Turn on warnings using the -Wall flag: the compiler often spots issues in the code.
If you are learning Haskell, I strongly suggest you refrain from using dangerous partial functions and read a tutorial on pattern patching, using which would prevent almost all the issues in your code.
For comparison, the code above could be rewritten as:
match :: Char -> Maybe String -> Maybe String
match x (Just (y:ys)) | x==y = Just ys
match _ _ = Nothing
Note how pattern matching simultaneously checks whether the argument is a Just with a non empty list inside, and extracts the data inside the constructors. When it fails, the next case of the match is taken (instead of crashing the program).
In languages without pattern matching (say, Java), often libraries force us to remember to check whether data is present (x.hasNext()) before accessing the data (x.next()). Forgetting the check causes a runtime error / exception. With pattern matching, these two steps are combined in the same language construct, so that there is no way to "forget" a check and crash the program.
Unlike the original code, match x (Just []) does not crash but returns Nothing instead.
fromJust expects to be passed a Just value and it receives a Nothingvalue, this is why this exception happens:
http://hackage.haskell.org/package/base-4.11.1.0/docs/Data-Maybe.html#v:fromJust
Note that I would encourage you to use the maybe function which could help clarify your code I think ( and ... maybe find the bug :) )
Also, maybe is preferable over fromJust because it's not a partial function (i.e it is guaranteed that the function won't error at runtime)
for example it allows you to rewrite :
match :: Char -> Maybe String -> Maybe String
match x input
| (isNothing input == False) && (x == head (fromJust(input))) = Just (tail (fromJust(input)))
| otherwise = Nothing
as
match :: Char -> Maybe String -> Maybe String
match x input =
maybe
Nothing
(\i ->
if x == head i
then Just $ tail i
else Nothing)
input
One more thing : head and tail are partial functions too, you'd prefer using pattern matching like this, to avoid runtime exceptions when the String is empty for example:
match :: Char -> Maybe String -> Maybe String
match x input =
maybe
Nothing
(\i -> case i of
[] -> Nothing
first:rest ->
if x == first
then Just rest
else Nothing)
input
(Edit: also, see the answer of #chi that gives a nice idiomatic implementation of match!)
Related
So I defined a 'match' function as follows
let match :: Eq a => a -> [a] -> [Int]; match x = map (fromEnum . (==x))
Now I'm trying to define a new 'countN' function that counts the matches. When I try
let countN :: a -> [a] -> Int; countN x xs = ? $ match x xs
I get errors of the form: 'parse error of input '?''
You're getting an error because the compiler is parsing ? as an operator, and it sees two operators in a row, the second being $, which is illegal syntax. It looks like you copy/pasted this from somewhere that had the ? there as something to fill in, what do you think goes there?
EDIT:
To elaborate, what would you make of an expression like
myFunc x = + * ++ / x
To humans and any Haskell compiler, this expression makes no sense. What do all of those operators mean there? It can't be composition, the types wouldn't line up, and there just aren't enough arguments. This is the sort of problem the compiler has when it sees ? $ match x xs.
I'm pretty brand new to Haskell (only written a fizzbuzz program before the current one) and am trying to write a program that takes the unix wordlist ('/usr/share/dict/words') and prints out the list of anagrams for that word, with any direct palindromes starred. I have the meat of this summed up into one function:
findAnagrams :: [String] -> [(String, [String])]
findAnagrams d =
[x | x <- map (\s -> (s, [if reverse s == t then t ++ "*" else t | t <- d, s /= t && null (t \\ s)])) d, not (null (snd x))]
However, when I run the program I get this output:
abase: babes, bases
abased: debase
abasement: basements
abasements: abatements
abases: basses
And so on, so clearly it isn't working properly. My intention is for the list comprehension to read as follows: for all t in d such that t is not equal to s and there is no difference between t and s other than order, if t is the reverse of s include as t*, otherwise include as t. The problem seems to be with the "no difference between t and s other than order" part, which I'm trying to accomplish by using "null (t \ s)". It seems like it should work. Testing in GHCI gives:
Prelude Data.List> null ("abatements" \\ "abasements")
False
And yet it passes the predicate test. My assumption is that I'm missing something simple here, but I've looked at it a while and can't quite come up with it.
In addition, any notes regarding best practice would be greatly appreciated.
If you break it out into multiple functions (remember, source code size is not really that important), you could do something like:
import Data.List
isPalindrome :: String -> Bool
isPalindrome s = s == reverse s
flagPalins :: [String] -> [String]
flagPalins [] = []
flagPalins (x:xs)
| isPalindrome x = x ++ "*"
| otherwise = x
isAnagram :: String -> String -> Bool
isAnagram s t = (isPalindrome s || s /= t) && ??? -- test for anagram
findAnagrams :: String -> [String] -> [String]
findAnagrams s ws = flagPalins $ filter (isAnagram s) ws
findAllAnagrams :: [String] -> [(String, [String])]
findAllAnagrams ws = filter (not . null . snd) ??? -- words paired with their anagrams
I've intentionally left some holes for you to fill in, I'm not going to give you all the answers ;)
There are only two spots for you to do yourself. The one in findAllAnagrams should be pretty easy to figure out, you're already doing something pretty similar with your map (\s -> ...) part. I intentionally structured isAnagram so it'll return True if it's a palindrome or if it's just an anagram, and you only need one more check to determine if t is an anagram of s. Look at the comment I made on your question for a hint about what to do there. If you get stuck, comment and ask for an additional hint, I'll give you the name of the function I think you should use to solve this problem.
If you really want to make a list comprehension, I would recommend solving it this way, then converting back to a comprehension. In general you should write more verbose code, then compress it once you understand it fully.
Think of a \\ b as "items in a that are not in b."
Consider the implications.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Iterating through a String and replacing single chars with substrings in haskell
I'm trying to implement a function that looks at a String ([Chars]) and checks for every letter whether this letter should be replaced with another string. For example we might have a [Chars] consisting of "XYF" and rules that says "X = HYHY", "Y = OO", then our output should become "HYHYOOF".
I want to use the following two types which I have defined:
type Letters = [Char]
data Rule = Rule Char Letters deriving Show
My idea is that the function should look something like the following below using guards. The problem is however I can't find any information on how to the recursive call should look like when i want browse through all my rules to see if any of them fits to the current letter x. I hope anyone can give some hints on how the notation goes.
apply :: Letters -> [Rule] -> Letters
apply _ _ = []
apply (x:xs) (Rule t r:rs)
| x /= t = apply x (Rule t rs)
| x == t = r++rs:x
| otherwise =
I would suggest a helper function to check whether a rule matches,
matches :: Char -> Rule -> Bool
matches c (Rule x _) = c == x
and then you check for each character whether there are any matching rules
apply :: Letters -> [Rule] -> Letters
apply [] _ = []
apply s [] = s
apply (c:cs) rules = case filter (matches c) rules of
[] -> c : apply cs rules
(Rule _ rs : _) -> rs ++ apply cs rules
If you try an explicit recursion on rules within apply, it will become too ugly, since you need to remember the full rules list for replacing later characters.
I'd suggest that you learn to do this with generic utility functions. Two key functions that you want here:
lookup :: Eq a => a -> [(a, b)] -> Maybe b. Finds a mapping in an association list—a list of pairs used to represent a map or dictionary.
concatMap :: (a -> [b]) -> [a] -> [b]. This is similar to map, but the function mapped over the list returns a list, and the results are concatenated (concatMap = concat . map).
To use lookup you need to change your Rule type to this more generic synonym:
type Rule = (Char, String)
Remember also that String is a synonym for [Char]. This means that concatMap, when applied to String, replaces each character with a string. Now your example can be written this way (I've changed argument orders):
apply :: [Rule] -> String -> String
apply rules = concatMap (applyChar rules)
-- | Apply the first matching rule to the character.
applyChar :: [Rule] -> Char -> String
applyChar rules c = case lookup c rules of
Nothing -> [c]
Just str -> str
-- EXAMPLE
rules = [ ('X', "HYHY")
, ('Y', "OO") ]
example = apply rules "XYF" -- evaluates to "HYHYOOF"
I changed the argument order of apply because when an argument has the same type as the result, it often helps to make that argument the last one (makes it easier to chain functions).
We can go further and turn this into a one-liner by using the utility function fromMaybe :: a -> Maybe a -> a from the Data.Maybe module (fromMaybe default Nothing = default, fromMaybe default (Just x) = x):
import Data.Maybe
apply rules = concatMap (\c -> fromMaybe [c] $ lookup c rules)
An exercise you can do to complement this is to write your version of all of these utility functions on your own by hand: lookup, concatMap (break it down into concat :: [[a]] -> [a] and map :: (a -> b) -> [a] -> [b]), and fromMaybe. That way you can understand the "full stack" involved in this solution.
My solution is structurally similar to the other ones, but uses monads:
import Control.Monad
import Data.Functor
import Data.Maybe
match :: Char -> Rule -> Maybe Letters
match c (Rule c' cs) = cs <$ guard (c == c')
apply :: Letters -> [Rule] -> Letters
apply cs rules =
[s | c <- cs
, s <- fromMaybe [c] $ msum $ map (match c) rules]
The first monad we're dealing with is Maybe a. It is actually a little bit more, a MonadPlus, which allows us to use msum (which boils down something like [Nothing, Just 2, Nothing, Just 3] to the first "hit", here Just 2).
The second monad is [a], which allows us to use a list comprehension in apply.
I am trying to learn some Haskell and I find it difficult. I am having some issues with my
current project. The idea is that I have to go through a String and substitute certain chars
with new substrings. For instance if I have a String "FLXF" and I want to replace every F
with a substring called "FLF" the result should be "FLFLXFLF". Now I have been working on this
specific problem for hours. I have been reading up on types, different functions that might come in handy (map, fold, etc) and yet I have not been able to solve this problem.
The code below is some of the different tries I have had:
apply :: String -> String
apply [] = []
apply (x:xs) = if (x == 'F')
then do show "Hello"
apply xs
else (apply (xs))
This example here I was just trying to show hello every time I encountered a 'F', but all it shows is "", so this clearly does not work. I am really not sure an if else statement is the way to go here. I was also thinking the function map might do the trick. Here the code I was thinking about could look something like this:
map (\x y -> if y == 'F' then "FLD" else y) "FLF"
but that gives me a type error. So as you can see I am lost. Excuse me my poor knowledge to Haskell, but I am still new to it. I really hope some of you can help me out here or give me a push in the right direction. Feel free to ask questions if I have been unclear about something.
Thank you in advance!
John
map (\x y -> if y == 'F' then "FLD" else y) "FLF"
This is nearly right.
First... why does the function take two arguments?
map (\y -> if y == 'F' then "FLD" else y) "FLF"
The remaining type error is because the then branch gives a String, but the else branch gives a Char (the two branches must each give a value of the same type). So we'll make the else branch give a String instead (recall that String is a synonym for [Char]):
map (\y -> if y == 'F' then "FLD" else [y]) "FLF"
Now the problem is that this gives you a [String] value instead of a String. So we'll concatenate all those strings together:
concat (map (\y -> if y == 'F' then "FLD" else [y]) "FLF")
This combination of concat and map is common enough that there's a standard function that combines them.
concatMap (\y -> if y == 'F' then "FLD" else [y]) "FLF"
concatMap is the most intuitive thing here. This kind of combination between mapping over a data structure a function that does itself return the type of the data structure (in this case, a list) and combining the results back into a single "tight" list is indeed very common in Haskell, and indeed not only for lists.
I'd like to explain why your first attempt compiles at all, and what it actually does – because it's completely different from what you probably think!
apply (x:xs) = if (x == 'F')
that line is still perfectly clear: you just take the first char off the string and compare it to 'F'. At bit "pedestrian" to manually take the string apart, but fine. Well, the name you gave the function is not particularly great, but I'll stick with it here.
then do show "Hello"
now this is interesting. You probably think do starts a list of points, "first do this, then do that"... like in simple Hello, World-ish example programs. But always remember: in Haskell, there's normally no such thing as an order in which stuff is calculated. That only happens in the IO context. But there's no IO in your code!?!
Not sure if you've heard about what IO actually is, anyway here you go: it's a Monad. Those "mythical Haskell constructs you've only read about in story books"...
Indeed, though this might lead a bit far here, this question covers all there is to know about Monads! How is that?
Here's another (correct!) way do define your function.
apply' str = do
x <- str
if (x == 'F')
then "FLF"
else return x
So I'm using this weird do syntax, and it's not in IO, and it looks completely different from what you'd write in IO, but it works. How?
x <- str
In do notation, variable <- action always means something like "take one value out of this monadic thingy, and call it x". What you've probably seen is something like
response <- getLine
which means "take a user input out of the real world (out of the IO monad!) and call it response". In x <- str, it's a string that we have, not an IO action. So we take a character out of a string – nice and easy!
Actually, it's not quite right, though. "take a character" is what you do with apply (x:xs) = ..., which simply takes the first one. In contrast, x <- str actually takes all possible characters out of the string, one by one. If you're used to procedural languages, this may seem very inconsistent with response <- getLine, but in fact it's not: getLine also consists of every possible input that the user might give, and the program has to act according to this.
if (x == 'F')
nothing unexpected here, but
then "FLF"
whoah! Just like that? Let's first look at the next line
else return x
ok, this looks familiar, but actually it's not. In other languages, this would mean "we're done with our function, x is the result". But that's obviously not what happens here, because x is Char, and the "return type" of apply' is String. In Haskell, return actually has little to do with returning values from a function, instead it means "put that value into the monadic context that we're working in". If the monad were IO, that would be quite the same: give this value back to the real-world context (this does not mean to print the value or something, just to hand it on). But here, our context is a string, or rather a list (of chars, so it is a String).
Right, so if x is not 'F' we put it back into the string. That sounds reasonable enough, but what about then "FLF"? Note that I can also write it this way:
if (x == 'F')
then do
x' <- "FLF"
return x'
else return x
which means, I take all characters out of "FLW" and return them back into the overall result. But there's no need to only think about the final result, we can as well isolate only this part do { x' <- "FLF"; return x' } – and, quite obviously, its value is nothing but the string "FLF" itself!
So I hope you have now grasped why apply' works. Back to your version, though it actually doesn't make much sense...
then do
show "Hello"
apply xs
here we have a line that's not at the end of a do block, but doesn't have a <- in it. You normally see this in IO in something like
main = do
putStrLn "How ya doin'?"
response <- getLine
...
Remember that "output-only" actions have type IO() in Haskell, which means, they don't directly return any meaningful value, just the trivial value (). So you don't really care about this, but you could still evaluate it:
main = do
trivial <- putStrLn "Hello, let's see what this IO action returns:"
print trivial
compiles and outputs
Hello, let's see what this IO action returns:()
It would be stupid if we had to do this evaluating () all the time, so Haskell allows to just leave the () <- out. It's really just that!
So a line like show "Hello" in the middle of a do block basically means "take one character out of show "Hello" (which is simply a string with the value "\"Hello\""), but don't do anything else with this character / just throw it away".
The rest of your definition is just other recursive calls to apply, but because none of them does anything more interesting than throwing away characters, you eventually end up at apply [] = [], so that's the final result: an empty string.
if-then-else... I know that Haskell supports these, however, I'm very surprised that no one here removed them...
So below are my solutions for different cases of making replacements.
Replacing a character
Replacing words
Replacing through a function on each word
$ cat replace.hs
import Data.List (isPrefixOf)
replaceC :: Char -> Char -> String -> String
replaceC _ _ [] = []
replaceC a b (x:xs)
| x == a = b:replaceC a b xs
| otherwise = x:replaceC a b xs
replaceW :: String -> String -> String -> String
replaceW a b s = unwords . map replaceW' $ words s
where replaceW' x | x == a = b
| otherwise = x
replaceF :: (String -> String) -> String -> String
replaceF f = unwords . map f . words
string = "Hello world ^fg(blue)"
main = do
print string
print $ replaceC 'o' 'z' string
print $ replaceW "world" "kitty" string
print . replaceF f . replaceW "world" "kitty" $ replaceC 'H' 'Y' string
where f s | "^" `isPrefixOf` s = '^':'^':drop 1 s
| otherwise = s
$ runhaskell replace.hs
"Hello world ^fg(blue)"
"Hellz wzrld ^fg(blue)"
"Hello kitty ^fg(blue)"
"Yello kitty ^^fg(blue)"
Your basic error was that you wanted to replace a Char in a String with a String.
This is impossible because String is a list of Char and a Char is a Char and not a short String. Neither is a String ever a Char, even if its length is 1.
Hence, what you really wanted is to replace some Char with some other Chars. Your approach was promising and could have been completed like so:
replace [] = [] -- nothing to replace in an empty string
replace (c:cs) = if c == 'F' then 'F':'L':'F':replace cs
else c:replace cs
I recently started learning Haskell and I'm trying to rewrite something I did for an interview in python in Haskell. I'm trying to convert a string from camel case to underscore separated ("myVariableName" -> "my_variable_name"), and also throw an error if the first character is upper case.
Here's what I have:
import qualified Data.Char as Char
translate_java :: String -> String
translate_java xs = translate_helper $ enumerate xs
where
translate_helper [] = []
translate_helper ((a, num):xs)
| num == 1 and Char.isUpper a = error "cannot start with upper"
| Char.isUpper a = '_' : Char.toLower a : translate_helper xs
| otherwise = a : translate_helper xs
enumerate :: (Num b, Enum b) => [a] -> [(a,b)]
enumerate xs = zip xs [1..]
I realize It's pretty likely I'm going about this in a weird way, and I'd love advice about better ways to implement this, but I'd like to get this to compile as well. Here's the error I'm getting now:
Prelude> :r
[1 of 1] Compiling Main ( translate.hs, interpreted )
translate.hs:4:20:
No instance for (Num
(([Bool] -> Bool) -> (Char -> Bool) -> Char -> t))
arising from a use of `translate_helper' at translate.hs:4:20-35
Possible fix:
add an instance declaration for
(Num (([Bool] -> Bool) -> (Char -> Bool) -> Char -> t))
In the first argument of `($)', namely `translate_helper'
In the expression: translate_helper $ enumerate xs
In the definition of `translate_java':
translate_java xs
= translate_helper $ enumerate xs
where
translate_helper [] = []
translate_helper ((a, num) : xs)
| num == 1 and Char.isUpper a
= error "cannot start with upper
"
| Char.isUpper a
= '_' : Char.toLower a : transla
te_helper xs
| otherwise = a : translate_help
er xs
Failed, modules loaded: none.
Any explanation of what's going on here would be great. I really don't understand where "(Num (([Bool] -> Bool) -> (Char -> Bool) -> Char -> t))" is coming from. I'd think the type declaration for translate_helper would be something like [(a,b)] -> [a]?
You have to replace and by &&. The first one is a function (prefix) that receives a list of boolean values and calculates an and of them all. The second one is a true logical and. The error message is a little bit confusing though. Whenever I get such a strange error message, I usually start to annotate my code with type signatures. Then the compiler is able to give you a more detailed description of what went wrong.
Others have mentioned that you should use (&&) instead of and, so I'll answer your other question: no, I don't think you're going about this in a weird way.
But... I do think it can be even more elegant!
translate_java (x:xs) | isUpper x = error "cannot start with an upper"
translate_java xs = concatMap translate xs where
translate x = ['_' | isUpper x] ++ [toLower x]
There's a few interesting things going on here:
The special case is checked straight away. Don't wait until you're recursing to do this!
The concatMap function is really handy in a lot of cases. It's just a map followed by a concat. If I were writing this myself, I'd probably use xs >>= translate instead.
That ['_' | isUpper x] is a list comprehension; this is a cute idiom for making a list with either 0 or 1 elements in it, depending on whether a predicate holds.
Other than that, the code should be fairly self-explanatory.
The problem is this:
| num == 1 and Char.isUpper a = ...
and is not an infix operator; rather it is a function:
and :: [Bool] -> Bool
So it is interpreting 1 and Char.isUpper a as applying three arguments to the "function" 1. Use && instead.
The error message comes from the way numerals are interpreted. A numeral, say, 1 is actually polymorphic; the specific type it gets depends on the type that is needed. That's why you can say x+1 and it will work whether x is an integer or a double or whatever. So the compiler inferred that the type of 1 needs to be a three-argument function, and then tried to find a numeric type matching that so it could convert 1 into that type (and, naturally, failed).
Here's my solution. It's not as masterful as the answer Daniel Wagner gave using concatMap and the list comprehension, but it's perhaps easier to understand for the beginner.
conv :: String -> String
conv [] = []
conv s#(x:xs) = if Char.isUpper x
then error "First character cannot be uppercase"
else change s
change :: String -> String
change [] = []
change (x:xs) = if Char.isUpper x
then '_' : Char.toLower x : change xs
else x : change xs
The function conv really just checks your criterion that the first character must not be uppercase, and if it isn't it hands over the string to the function change, which does the work. It goes through all the characters one by one, building a list, and if the character is uppercase, it adds an underscore followed by the lowercase version of the character, otherwise if the character is already lowercase it just adds it as it is.