emptyAndOther
:: IO (Int, Int)
emptyAndOther =
do
c <- getChar
if c == '\ESC'
then return (x, y)
else if isSpace c
then (x+1) y
else x (y+1)
where
x = 0
y = 0
What is wrong with this code?
I want to count every empty line and every char and on ESC button, return the result.
Dont seem to understand, what is wrong
yes, i must use this signature
The problem lies in the fact that your else branches are attempting to call x as a function, which is a weird thing to do, since it's a number instead. I suggest trying to write a helper function
emptyAndOther' :: Int -> Int -> IO (Int, Int)
such that emptyAndOther = emptyAndOther' 0 0. For the future, I would point out that carefully reading error messages helps a lot. For example, GHC's error message says almost exactly what I did (though in terser language):
The function `x + 1' is applied to one argument,
but its type `Int' has none
In the expression: (x + 1) y
Here's a question in response. In the code:
else if isSpace c
then (x+1) y
else x (y+1)
What do the expressions (x+1) y and x (y+1) mean? I'm guessing you're trying to increment x and y, but haskell doesn't work that way.
Instead, try having emptyAndOther take the current value of x and y, and then recurse in those two cases by calling emptyAndOther (x+1) y or emptyAndOther x (y+1).
Your function has return type IO (Int,Int)
Now lets see the 3 branches in if/else
If part results in return (x, y) which is good as this will return a IO (Int,Int) and thats what your function return type is
Now in the else if and else part, the result seems to doesn't imply with the fact that your function return type is IO (Int,Int) .
Both the else if and else expressions should result in IO (Int,Int) type. This is just a hint. If you have worked in other programming language like C# and Java and try to write a function which return a string but in if part you return string and in else part you return int. That won't work .. same problem applies here
Related
I am trying to write a basic function in Haskell as shown below. My aim is provide the code to square only even numbers while odd numbers will stay same. Would you please help me regarding this issue.
square:: Int -> Int
square x = [ x*x | x <- [1..10], mod x 2 == 0 ]
regards
You are here filtering. You should determine if the number is even or odd and then square the number or not, this can be done in the yield part of the list comprehension.
But the type signature hints that you do not need to construct a list at all. You simply check if the parameter x is even, and if that is the case return x*x, otherwise return x:
square:: Int -> Int
square x = if even x then x*x else x
or through guards:
square:: Int -> Int
square x
| even x = x*x
| otherwise = x
One quite straightforward answer to your question is, you can inline a if statment directly into your list comprehension like so:
[ if even x then x * x else x | x <- [1..10] ]
This is possible since if is an expression in Haskell, meaning it evaluates to a value, so things like this are valid:
let _ = if 1 + 1 == 2 then "foo" else "bar"
It can also be good to look at this problem in another direction. List comprehensions can be quite nice, but sticking an if within it can get pretty messy. Willem's solution of factoring out the method is great, so let's look at other ways we can leverage it with your code:
-- This is the function we're trying to implement
evenSquares :: [Int] -> [Int]
-- We could start by noting that `if` expression has a nice name,
-- which can be factored out to make things look cleaner
-- Same implementation as Willem's
evenSquares xs = [ squareIfEven x | x <- xs ] where
squareIfEven x = if even x then x * x else x
-- List comprehensions are nice, but there's also another name for what we're doing,
-- which is mapping over a collection of values and applying a method
evenSquares xs = map squareIfEven xs where
squareIfEven x = if even x then x * x else x
-- Note how the `xs` is an argument to `evenSquares` and also the last argument to `map`
-- We can actually get rid of `xs` entirely via this rule:
-- https://wiki.haskell.org/Eta_conversion
evenSquares = map squareIfeven where
squareIfEven x = if even x then x * x else x
-- This one's a bit of a stretch, but conceptually quite useful
-- The idea of 'apply a method if a condition is true' can be expressed as a method
-- which takes a predicate method, a transformation method, and a value
-- We can leverage this ourselves to make `squareIfEven` more generic too
evenSquares = map (if' even square id) where
square x = x * x
if' pred fst snd x = if pred x then fst x else snd x
-- There's a bunch more solutions we can try, including things like `do` notation
-- This is just an idea of how you could look at your problem
-- Pick one which makes your solution clear and concise!
If i'm creating a function, let's take the simplest example:
add x y = x + y
if i want to add a Function Type declaration before, for clarity sake
add :: (Int, Int) -> Int
add x y = x + y
I get a compile error:
"Couldn't match expected type ‘Int’ with actual type ‘(Int, Int) -> (Int, Int)’".
"The equation(s) for ‘add’ have two arguments, but its type ‘(Int, Int) -> Int’ has only one"
but it compiles flawlessly if i correct it to
add :: (Int, Int) -> Int
add (x, y) = x + y
coming from other languages, i actually think it's clearer to use the second form with parenthesis, but in my opinion, both ways should work
1 - what is the reason for not working the first way?
2 - i find the error messages completely confusing so, maybe, the error happens for another reason i don't understand
what is the reason for not working the first way?
In the first expression your type says it takes a 2-tuple as single parameter, and it returns the sum of the two items. But in the "body" of the function, you specify add x y = x + y hence you construct a function that takes a parameter x that will return a function that will take a parameter y which maps to x + y.
In Haskell all functions take one parameter. Indeed, your add function takes one parameter x. It is short for:
add x = \y -> x + y
It thus returns a function that will take a parameter y and then maps y to x + y. If you thus construct a function f = add 2, then f will take the parameter y, and map this on 2 + y.
The arrow is a right-associative operator. This means that Int -> Int -> Int is short for Int -> (Int -> Int), it thus is a function that maps an Int to another function.
You can see the syntax of languages like Java where they call f (x, y) basically as calling the function f with one object: a 2-tuple with x and y as its two elements.
So I'm trying to create a helper function that does something else, but I can't even get past the helper function because I keep getting this error:
Couldn't match expected type ‘[Char]’ with actual type ‘Int -> [t -> t1]’
freqsHelper x = freqs (x (lowers x))
^
The lowers(x) is causing the issue. Here is my code:
lowers [] = 0
lowers (x:xs)
| isLower x == True = 1 + lowers xs
| otherwise = lowers xs
count _ [] = 0
count x (y:ys)
| x == y = 1 + count x ys
| otherwise = count x ys
percent x y = x/y*100
freqsHelper x = freqs (x (lowers x))
freqs (x:xs) y = percent ((count (x (x:xs))) y) : freqs xs y
You’d be well-advised to add type declarations for every top-level function. Let’s follow what the type deduction system is doing here when it tries to figure this out.
The problem is not with lowers, which takes a [Char] as its argument and returns an Int.
The freqsHelper x declaration has one argument, x, whose type we’ll call a while we try to figure it out. We’ll call the return type b. So, freqsHelper is a function of type a -> b.
It’s also equal to freqs (x (lowers x)). So, x, which has type a, must be a function which takes the result of lowers as its argument. We know that lowers is [Char] -> Int, so a must be a function of type Int -> t1, where t1 is some type we would need to deduce from freqs. However, x is also passed as the argument of lowers. Which expects [Char], not a function with one argument. So we already have a contradiction.
So, there’s your mismatch. In the definition of freqsHelper, you’re using x in a context where Haskell expects a string, but also in a context where x has to be some kind of function. I’m pretty sure there’s a bug in freqs as well, given that it calls a function of two numeric arguments with only one argument.
Ah, I think I know what you're getting at. You're close. A couple things - if you're gonna do a division, you should do a fromIntegral to get back some kind of fractional.
percent :: (Fractional a) => Int -> Int -> a
percent x y = (fromIntegral x / fromIntegral y) * 100
I think your frequency is trying to get the frequency of something in a list, in which case you'll need a base case:
freqs [] y = []
freqs (x:xs) y = percent (count x y) (length y) : freqs xs y
I think you can figure out the rest from here.
A few style hints - you can use a map for freqs:
freqs' x y = map (\a -> percent (count a y) $ length y) x
The compiler will probably do it for you, but you can explicitly call out length y:
freqs' x y = map (\a -> percent (count a y) len) x
where len = length y
freqsHelper x = freqs (x (lowers x))
Let's break this down.
lowers x
You call lowers with x as input, so x must be a string.
x (lowers x)
But you call x as a function, passing it the result of lowers as input. So x must be a function that takes an Int as input. (That sounds like a mistake...)
freqs (x (lowers x))
You call freqs with the output from calling the x function... so x must return a list of some kind?
At this point, the type checker is confused as to what the heck x is even supposed to be, so it gives up.
Perhaps you meant to pass x and lowers x as two separate arguments? In that case, you want
freqs x (lowers x)
By putting brackets around x (lowers x), you make the compiler think that x is a function you want to call, with lowers x as the argument. I doubt you meant to do that.
As a side note, if you add type signatures on each of the functions you've defined, you may get a clearer indication from the type checker as to which bit is actually wrong. (As it is, the type checker can see the types don't line up, but can't actually determine where the types deviate from what you intended — because it cannot read your mind to know what you intended...)
At HaskellWiki's Do notation considered harmful, section Useful applications, I found:
It shall be mentioned that the do sometimes takes the burden from you
to write boring things.
E.g. in
getRight :: Either a b -> Maybe b
getRight y =
do Right x <- y
return x
a case on y is included, which calls fail if y is not a Right (i.e.
Left), and thus returns Nothing in this case.
Calling fail (Nothing) on a pattern mismatch sounds interesting, so I wanted to try this out. However, the syntax looks wrong - we're not in the Either monad, so how can we extract anything from y?
Indeed, I tried and it gave me "Couldn't match type `Either a' with `Maybe'". So let's use the correct pattern matcher, let in here:
getRight y = do { let (Right x) = y; return x }
That gave me a syntax error "parse error on input `}'". Not that I understand why this doesn't work, but let's write it out in multiline notation:
getRight y = do
let (Right x) = y
return x
Ah, that seemed to work - parse at least. However:
*Main> getRight (Right 5)
Just 5
*Main> getRight (Left 5)
Just *** Exception: […]\test.hs:16:13-25: Irrefutable pattern failed for pattern (Data.Either.Right x)
-- `Nothing` was expected
What gives? So my questions are now:
What happened here? Why did my semicolon-brace line not work?
How to do it correctly (with do, everything else is trivial)?
The example is probably meant to be
getRight :: Either a b -> Maybe b
getRight y =
do Right x <- return y -- note: return = Just
return x
where the pattern match failure calls fail = const Nothing. It is translated into:
getRight y = let ok (Right x) = do {return x}
ok _ = fail "pattern mismatch error"
in return y >>= ok
FWIW most experienced folks seem to think fail as a Monad method was a wart. Check out MonadPlus for a maybe more principled approach to failure.
I'm very new to haskell, writing a simple code that returns how many inputs are larger than their average value. I got error:
ERROR file:.\AverageThree.hs:5 - Type error in application
* Expression : x y z
Term : x
Type : Int
* Does not match : a -> b -> c
Code:
averageThree :: Int -> Int -> Int -> Float
averageThree x y z = (fromIntegral x+ fromIntegral y+ fromIntegral z)/3
howManyAverageThree ::Int -> Int -> Int -> Int
howManyAverageThree x y z = length > averageThree
Anyone help me?
The trouble you're having comes from a few places.
First, you aren't applying either function, length or averageThree - and hence also not using your arguments to howManyAverageThree.
Second, the type of length is [a] -> Int. As you don't have a list here, you either have to use a different function, or make a list.
If I understand your desired algorithm correctly, you are going to need to do a few things:
Apply x y and z to averageThree.
Use the filter function, comparing this computed average with each passed in parameter; this will result in a list.
Find the length of the resulting list.
The code I dashed off to do this follows:
howManyAverageThree ::Int -> Int -> Int -> Int
howManyAverageThree x y z = length $ filter (> avg) the_three
where avg = averageThree x y z
the_three = [fromIntegral x,fromIntegral y,fromIntegral z]
This takes advantage of a couple of neat features:
Currying, sometimes called "partial function application". That's what I was using with (> avg); normally, the infix function > takes two parameters of the same type, and returns a Bool - by wrapping in parenthesis and providing an expression on one side, I have partially applied it, which allows it to be used as a filter function
The where keyword. I used this to clean it all up a little and make it more readable.
The filter function, which I mentioned above.
Function application using $. This operator just changes the function application from left-associative to right-associative.
There are a number of problems here:
length doesn't do what you want it to. length returns the length of a list, and there are no lists in your howManyAvergageThree
averageThree returns a Float. howManyAverageThree needs to account for that. Specifically, > needs its arguments to be of the same type.
The call to averageThree in the second function needs some arguments.
Here's a working version:
howManyAverageThree x y z = length [ i | i <- [x, y, z], fromIntegral i > avg]
where avg = averageThree x y z