I'm an amateur at Haskell, trying to run through an infinite list of approximations to the square root of "x", where "acc" represents the generation this step is on. However, when I run the code below, I get the underlying error.
as' x acc = ( last(take (acc-1) (as' x (acc-1)))
+ (acc / last(take (acc-1) (as' x (acc-1)))) ) / 2 : as' x (acc+1)
ERROR "a5.hs":34 - Instance of Fractional Int required for definition of as'
Also, when I try applying this type code, I get an error:
as' :: Float -> Float -> Float
Type error in application
*** Expression : (last (take (acc - 1) (as' x (acc - 1))) + acc / last (take (acc - 1) (as' x (acc - 1)))) / 2 : as' x (acc + 1)
*** Term : as' x (acc + 1)
*** Type : Float
*** Does not match : [a]
EDIT: To offer you some clarity, I want to use this function in the context of a list.
e.g. as x = [1, as' x 2].
The idea is that this will accumulate an infinite list, since as' will recursively call itself. Hence why I felt I could operate on a list here.
Can anyone please offer me some clarity?
The type signature of take is
take :: Int -> [a] -> [a]
Here's how you are using take:
take (acc-1) (as' x (acc-1))
So we can conclude that
(acc-1) :: Int -- first parameter to `take`
acc :: Int -- therefore
(as' x (acc-1)) :: [a] -- second parameter to `take`, we don't know what `a` is
But your code says
as' :: Float -> Float -> Float
as' x acc = ...
From which we deduce
x :: Float -- first parameter to `as'`
acc :: Float -- second parameter to `as'`
(as' x (acc-1)) :: Float -- result of `as'`
Which leads to a couple of contradictions:
acc cannot be an Int and a Float at the same time
(as' x (acc-1)) cannot be an [a] and a Float at the same time --- this is what the second error message is trying to tell you
Ultimately, you are trying to use take on something that is not a list. I'm not sure what you are trying to do.
You probably intended to have the signature
as' :: Float -> Int -> [Float]
That should (I've not tested it) fix the type errors above, but still leaves a more fundamental problem: whenever you compute the nth element of the list, you compute the *n-1*th element of the list anew twice (and so on, back to the start of the list: exponential growth of recalculation), even though presumably this element has already been computed. There is no sharing going on.
e.g. consider
as' x acc = ( prev + (acc / prev) ) / 2 : as' x (acc+1)
where prev = last(take (acc-1) (as' x (acc-1)))
This is still inefficient: you still recompute previous elements of the list. But now you only recompute all previous elements once when computing the next element.
(It would also be remiss of me not to point out that last(take (acc-1) (as' x (acc-1))) can be simplified to (as' x (acc-1)) !! (acc-2).)
The usual way to generate an infinite list where each element depends only on the previous element is to use iterate.
The complication is that you have each element depending on an accumulator as well as depending on the previous element. We will get round that by incorporating the accumulator into each element of the list. When we are done we will throw away the accumulators to produce our final infinite list.
approxRoots :: Float -> [Float]
approxRoots x = map fst $ iterate next (x, 1)
-- I don't know what your initial approximation should be
-- I've put `x` but that's probably wrong
where next (prev, acc) = (prev + acc / prev, acc + 1)
-- First element of each pair is the approximation,
-- second element of each pair is the "accumulator" (actually an index)
-- I've probably transcribed your formula wrongly
dave4420's answer is already very nice, I just want to share how you can get the most from the error message which the compiler gave you. Here is it again:
*** Expression : (last (take (acc - 1) (as' x (acc - 1))) + acc / last (take (acc - 1) (as' x (acc - 1)))) / 2 : as' x (acc + 1)
*** Term : as' x (acc + 1)
*** Type : Float
*** Does not match : [a]
This means that the as' x (acc + 1) part in the long expression was expected to yield a list, but it actually gives a Float value.
Why does the compiler expect it to be a list? Well, let's see where the term is used in the expression:
(last .... ) / 2 : as' x (acc + 1)
I.e., it's used as the second argument to the (:) function, and the compiler knows that the second argument to this function has to be a list (the compiler knows that the signature of (:) is a -> [a] -> [a] though it doesn't mention that part in the error message).
Why is it actually a Float? Since you didn't provide a function signature, the compiler deduced it for you and actually printed it as well:
as' :: Float -> Float -> Float
So the compiler determined that as' takes two Float values and yields a Float value. I don't know from the top of my head why it did that.
My advice is to start debugging this issue by explicitely writing down a function signature yourself. Doing so will cause a different error message which is closer to the cause of the mismatch between your expectation and the actual code.
Related
I have defined a typeclass Differentiable to be implemented by any type which can operate on infinitesimals.
Here is an example:
class Fractional a => Differentiable a where
dif :: (a -> a) -> (a -> a)
difs :: (a -> a) -> [a -> a]
difs = iterate dif
instance Differentiable Double where
dif f x = (f (x + dx) - f(x)) / dx
where dx = 0.000001
func :: Double -> Double
func = exp
I have also defined a simple Double -> Double function to differentiate.
But when I test this in the ghc this happens:
... $ ghci
GHCi, version 8.8.4: https://www.haskell.org/ghc/ :? for help
Prelude> :l testing
[1 of 1] Compiling Main ( testing.hs, interpreted )
Ok, one module loaded.
*Main> :t func
func :: Double -> Double
*Main> derivatives = difs func
*Main> :t derivatives
derivatives :: [Double -> Double]
*Main> terms = map (\f -> f 0) derivatives
*Main> :t terms
terms :: [Double]
*Main> take 5 terms
[1.0,1.0000004999621837,1.000088900582341,-222.0446049250313,4.440892098500626e8]
*Main>
The approximations to the nth derivative of e^x|x=0 are:
[1.0,1.0000004999621837,1.000088900582341,-222.0446049250313,4.440892098500626e8]
The first and 2nd derivatives are perfectly reasonable approximations given the setup, but suddenly, the third derivative of func at 0 is... -222.0446049250313! HOW!!?
The method you're using here is a finite difference method of 1st-order accuracy.
Layman's translation: it works, but is pretty rubbish numerically speaking. Specifically, because it's only 1st-order accurate, you need those really small steps to get good accuracy even with exact-real-arithmetic. You did choose a small step size so that's fine, but small step size brings in another problem: rounding errors. You need to take the difference f (x+δx) - f x with small δx, meaning the difference is small whereas the individual values may be large. That always brings up the floating-point inaccuracy – consider for example
Prelude> (1 + pi*1e-13) - 1
3.141931159689193e-13
That might not actually hurt that much, but since you then need to divide by δx you boost up the error.
This issue just gets worse/compounded as you go to the higher derivatives, because now each of the f' x and f' (x+δx) has already an (non-identical!) boosted error on it, so taking the difference and boosting again is a clear recipe for disaster.
The simplest way to remediate the problem is to switch to a 2nd-order accurate method, the obvious being central difference. Then you can make the step a lot bigger, and thus largely avoid rounding issues:
Prelude> let dif f x = (f (x + δx) - f(x - δx)) / (2*δx) where δx = 1e-3
Prelude> take 8 $ ($0) <$> iterate dif exp
[1.0,1.0000001666666813,1.0000003333454632,1.0000004990740052,0.9999917560676863,0.9957312752106873,8.673617379884035,7806.255641895632]
You see the first couple of derivatives are good now, but then eventually it also becomes unstable – and this will happen with any FD method as you iterate it. But that's anyway not really a good approach: note that every evaluation of the n-th derivative requires 2 evaluations of the n−1-th. So, the complexity is exponential in the derivative degree.
A better approach to approximate the n-th derivative of an opaque function is to fit an n-th order polynomial to it and differentiate this symbolically/automatically. Or, if the function is not opaque, differentiate itself symbolically/automatically.
tl;dr: the dx denominator gets small exponentially quickly, which means that even small errors in the numerator get blown out of proportion.
Let's do some equational reasoning on the first "bad" approximation, the third derivative.
dif (dif (dif exp))
= { definition of dif }
dif (dif (\x -> (exp (x+dx) - exp x)/dx))
= { definition of dif }
dif (\y -> ((\x -> (exp (x+dx) - exp x)/dx) (y+dx)
- (\x -> (exp (x+dx) - exp x)/dx) y
)/dx)
= { questionable algebra }
dif (\y -> (exp (y + 2*dx) - 2*exp (y + dx) + exp y)/dx^2)
= { alpha }
dif (\x -> (exp (x + 2*dx) - 2*exp (x + dx) + exp x)/dx^2)
= { definition of dif and questionable algebra }
\x -> (exp (x + 3*dx) - 3*exp (x + 2*dx) + 3*exp (x + dx) - exp x)/dx^3
Hopefully by now you can see the pattern we're getting into: as we take more and more derivatives, the error in the numerator gets worse (because we are computing exp farther and farther away from the original point, x + 3*dx is three times as far away e.g.) while the sensitivity to error in the denominator gets higher (because we are computing dx^n for the nth derivative). By the third derivative, these two factors become untenable:
> exp (3*dx) - 3*exp (2*dx) + 3*exp (dx) - exp 0
-4.440892098500626e-16
> dx^3
9.999999999999999e-19
So you can see that, although the error in the numerator is only about 5e-16, the sensitivity to error in the denominator is so high that you start to see nonsensical answers.
I want to add two positive numbers together without the use of any basic operators like + for addition. I've already worked my way around that (in the add''' function) (i think) may not be efficient but thats not the point right now. I am getting lots of type errors however which i have no idea how to handle, and is very confusing for me as it works on paper and i've come from python.
add 1245 7489
--add :: Int -> Int -> Int
add x y = add'' (zip (add' x) (add' y))
where
add' :: Int -> [Int]
add' 0 = []
add' x = add' (x `div` 10) ++ [x `mod` 10]
conversion [1,2,4,5] [7,4,8,9] then zipping them together [(1,7),(2,4)....]
add'' :: [(Int,Int)] -> [Int]
add'' (x:xs) = [(add''' (head x) (last x))] ++ add'' xs
summary [8,6,...] what happens when the sum reaches 10 is not implemented yet.
where
--add''' :: (Int,Int) -> Int
add''' x y = last (take (succ y) $ iterate succ x)
adding two numbers together
You can't use head and last on tuples. ...Frankly, you should never use these functions at all because they're unsafe (partial), but they can be used on lists. In Haskell, lists are something completely different from tuples.To get at the elements of a tuple, use pattern matching.
add'' ((x,y):xs) = [add''' x y] ++ add'' xs
(To get at the elements of a list, pattern matching is very often the best too.) Alternatively, you can use fst and snd, these do on 2-tuples what you apparently thought head and last would.
Be clear which functions are curried and which aren't. The way you write add''', its type signature is actually Int -> Int -> Int. That is equivalent to (Int, Int) -> Int, but it's still not the same to the type checker.
The result of add'' is [Int], but you're trying to use this as Int in the result of add. That can't work, you need to translate from digits to numbers again.
add'' doesn't handle the empty case. That's fixed easily enough, but better than doing this recursion at all is using standard combinators. In your case, this is only supposed to work element-wise anyway, so you can simply use map – or do that right in the zipping, with zipWith. Then you also don't need to unwrap any tuples at all, because it works with a curried function.
A clean version of your attempt:
add :: Int -> Int -> Int
add x y = fromDigits 0 $ zipWith addDigits (toDigits x []) (toDigits y [])
where
fromDigits :: Int -> [Int] -> Int
fromDigits acc [] = acc
fromDigits acc (d:ds)
= acc `seq` -- strict accumulator, to avoid thunking.
fromDigits (acc*10 + d) ds
toDigits :: Int -> [Int] -> [Int] -- yield difference-list,
toDigits 0 = id -- because we're consing
toDigits x = toDigits (x`div`10) . ((x`mod`10):) -- left-associatively.
addDigits :: Int -> Int -> Int
addDigits x y = last $ take (succ x) $ iterate succ y
Note that zipWith requires both numbers to have the same number of digits (as does zip).
Also, yes, I'm using + in fromDigits, making this whole thing pretty futile. In practice you would of course use binary, then it's just a bitwise-or and the multiplication is a left shift. What you actually don't need to do here is take special care with 10-overflow, but that's just because of the cheat of using + in fromDigits.
By head and last you meant fst and snd, but you don't need them at all, the components are right there:
add'' :: [(Int, Int)] -> [Int]
add'' (pair : pairs) = [(add''' pair)] ++ add'' pairs
where
add''' :: (Int, Int) -> Int
add''' (x, y) = last (take (succ y) $ iterate succ x)
= iterate succ x !! y
= [x ..] !! y -- nice idea for an exercise!
Now the big question that remains is what to do with those big scary 10-and-over numbers. Here's a thought: produce a digit and a carry with
= ([(d, 0) | d <- [x .. 9]] ++ [(d, 1) | d <- [0 ..]]) !! y
Can you take it from here? Hint: reverse order of digits is your friend!
the official answer my professor gave
works on positive and negative numbers too, but still requires the two numbers to be the same length
add 0 y = y
add x y
| x>0 = add (pred x) (succ y)
| otherwise = add (succ x) (pred y)
The other answers cover what's gone wrong in your approach. From a theoretical perspective, though, they each have some drawbacks: they either land you at [Int] and not Int, or they use (+) in the conversion back from [Int] to Int. What's more, they use mod and div as subroutines in defining addition -- which would be okay, but then to be theoretically sound you would want to make sure that you could define mod and div themselves without using addition as a subroutine!
Since you say efficiency is no concern, I propose using the usual definition of addition that mathematicians give, namely: 0 + y = y, and (x+1) + y = (x + y)+1. Here you should read +1 as a separate operation than addition, a more primitive one: the one that just increments a number. We spell it succ in Haskell (and its "inverse" is pred). With this theoretical definition in mind, the Haskell almost writes itself:
add :: Int -> Int -> Int
add 0 y = y
add x y = succ (add (pred x) y)
So: compared to other answers, we can take an Int and return an Int, and the only subroutines we use are ones that "feel" more primitive: succ, pred, and checking whether a number is zero or nonzero. (And we land at only three short lines of code... about a third as long as the shortest proposed alternative.) Of course the price we pay is very bad performance... try add (2^32) 0!
Like the other answers, this only works for positive numbers. When you are ready for handling negative numbers, we should chat again -- there's some fascinating mathematical tricks to pull.
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...)
Trying to return a list with the last element removed. Why am I getting this error?
ERROR file:.\ShrinkByOne.hs:5 - Type error in application
*** Expression : (lis !! n : result) lis n
*** Term : (:)
*** Type : f -> [f] -> [f]
*** Does not match : a -> b -> c -> d -> e
shrinkByOne :: [Int] -> [Int] -> Int -> [Int]
shrinkByOne result lis n
| n <= ((length lis) - 2) = shrinkByOne ( ((lis !! n):result) lis n+1) -- this condition prevents the last element from being returned
| otherwise = result
Why the error?
In your original code, you had something like that:
shrinkByOne (... something ...)
which meant that you applied only one argument to shrinkByOne. You need this instead:
shrinkByOne (... something ...) (... something ...) (... something ...)
Therefore, put parentheses this way:
shrinkByOne :: [Int] -> [Int] -> Int -> [Int]
shrinkByOne result lis n
| n <= ((length lis) - 2) = shrinkByOne ((lis !! n):result) lis (n+1) -- this condition prevents the last element from being returned
| otherwise = result
Other remarks
However, you will still not get the desired result, as the result will be reversed and the !! is expensive, and your function will be of Θ(n²) complexity.
Try a much simpler, linear approach:
shrinkByOne' :: [Int] -> [Int]
shrinkByOne' [x] = []
shrinkByOne' (x : xs) = x : shrinkByOne' xs
Finally, I understand that this is an exercise to learn Haskell. If it's not, simply use the init function from the Prelude.
First, you want to leave out unneeded parens around function arguments. f(x) is written f x in Haskell (that one's just optional), and in particular you can't write g (x y) if g :: A -> B -> C, it needs to be g x y (or possibly g (x) (y). But g (x y) would mean, you apply the function x to the argument y, and use the result as argument for g. (If you actually want that, write g $ x y, or g . x $ y.)
So that would mean shrinkByOne ((lis !! n):result) lis n+1. Which would, however, be parsed as (shrinkByOne ((lis !! n):result) lis n) + 1: infix operators like + always have lower precedence than function application, so indeed around n+1 you do need parens.
sum :: (Num a) => [a] -> a
sum xs = foldl (\acc x -> acc + x) 0 xs
foldl is folds the list up from the left side. So first we get the acc=0 and put the list xs to x ,then doing the function ->acc+x.After calculation, we get the new acc which is equal to acc+x. But why is that? I think this result of acc+x is the new value of x based on the function x->acc+x.
Let's take a look at your definition of sum
sum :: (Num a) => [a] -> a
sum xs = foldl (\acc x -> acc + x) 0 xs
Let's also take a peek at foldl's signature:
foldl :: (a -> b -> a) -> a -> [b] -> a
Hmm, ok, what do we have to feed foldl in order to get the value at the very, very end (->a)?
It needs a curried function (a->b->a). All though not accurate, for brevity's sake, we'll say its a function that takes two arguments (but you and I know that really, it takes one argument and returns another function that takes one argument).
It needs a value of type a. Notice that our curried function from Step 1. takes something of type a and returns something of type a. Interesting...hmmm...
It needs a list of type b. Notice our curried function from Step 1 takes, as well as something of type a, something of type b.
So, do we give it what it wants?
We give it (\acc x -> acc + x). This is an anonymous function, or lambda, that takes two arguments, (remember, it's curried, though), acc and x, and return's their sum.
We give it 0 as our starting value
We give it xs as the list to fold.
Ok dokie. So, let's just let foldl work its Haskell magic. Let's imagine we called sum [1,2,3]
foldl calls our function (\acc x -> acc + x), using 0 for acc and the first value of xs, 1.
0 + 1
This result does not get stored away in acc or x, since they are just arguments in our little lambda function. foldl is going to use that value (see SanSS's answer for the specific implementation).
Remember that the result of our lambda function is the same type as the first parameter? foldl can use that previous sum and pass it back to the lambda function, along with the second element.
(0 + 1) + 2
And again until it has done this for all the elements:
((0 + 1) + 2) + 3
6
As pointed out by Dan, this is the same if you had done:
sum xs = foldl (+) 0 xs
You can tell more easily with this function that we aren't just 'setting' some variable and adding onto it.
Hope this helps.
Side note:
For your definition of sum, you don't have to explicitly state that sum takes xs. You could leave it as:
sum = foldl (\acc x -> acc + x) 0
This takes advantage of currying, because if we provide foldl just its first two arguments -- a curried function like (a->b->a) and a value of type a -- what do we get?
[b] -> a
A function that takes a list of type b and returns a value of type a! This is called pointfree style. Just something to consider :-)
You should look at the definition of foldl:
foldl f z [] = z
foldl f z (x:xs) = foldl f (f z x) xs
foldl recieves a funcion which takes 2 arguments, a value (the "starter value" or accumulator) and a list.
In case the list is empty it returns the current calculation.
If the case is not empty then it calls recursively with the same function as function, the accumulator is the result of the invocation of the function using the accumulator as the first argument and the first element of the list as the second argument and the tail of the list is used as the list for the recursive call.
So the lambda function used in sum becomes quite clear it takes acc as first argument and the element of the list as second argument and return the sum of both.
The result of the invocations for:
sum [1,2,3] = ((0 + 1) + 2) + 3 = 6
From your question, it sounds like you don't understand how the lambda function (\acc x -> acc + x) works here.
The function is not x->acc+x, but acc x->acc + x. In fact, you could rewrite the "sum" equation as
sum xs = foldl (+) 0 xs
Since (\acc x -> acc + x) is the same as (+)
I suggest you (re)read http://learnyouahaskell.com/higher-order-functions#lambdas