this exercise is driving me crazy. I mean, I know how Scope and Binding work but I can only understand easy examples. In this case, I'm not able to solve the exercise, it's too tricky.
For example,
1. {int x = 1;
2. int y = 1;
3. int f (int y) {
4. x = y+x;
5. return x}
6. int g (int -> int h, int y) {
7. int x = 2;
8. y = f(x);
9. return h(y)}
10. int x = 3;
11. y = g(f,x);}
what is the value of y in line 11 considering these cases?
Static Deep Binding
Dinamic Deep Binding
Dinaming Shallow Binding
Sorry for my english
Thank you
Related
I'm relatively new to Haskell, so I am working through some old Advent of Code problems to familiarize myself with the language.
However, I got stuck on 2017 day 17, part two.
I've tried three solutions to this problem.
(Edit: reduced the code block to a clearer example)
The following solution is something I would expect to work moderately efficiently:
run :: IO()
run = do
print "Starting:"
print (iteration''' 0 1 3 0 50000000)
iteration''' :: Int -> Int -> Int -> Int -> Int -> (Int, Int, Int, Int)
iteration''' cp cv ss zv 0 = (cp, cv, ss, zv)
iteration''' cp cv ss zv count = iteration''' ncp ncv ss nzv (count - 1)
where
ncp = ((cp + ss) `mod` cv) + 1
nzv = if ncp == 1 then cv else zv
ncv = cv + 1
The problem is that all three are horribly inefficient, both memory-wise and CPU-wise.
The equivalent C-code would be something like the following (completing very quickly).
int stepSize = 3;
int zv = 0;
int position = 0;
for (int i = 0; i < 50000000; i++) {
position = (position + stepSize) % i;
if (position == 0) zv = i;
}
I assumed iteration''' would be able to compile to something similar - but it eats up gigabytes of memory and loops for a long time.
To summarize my question - what is an idiomatic way to "solve this problem efficiently" in Haskell? Why is it eating up so much heap space when there is no actual object turnover necessary?
I am compiling using ghc (cabal).
For completeness, as answered by Daniel Wagner and chi:
The problem in the stated code was strictness (implicitly a large amount of lazily evaluated ints resulted in a large amount of overhead).
This method is a lot faster (adding the BangPatterns header)
iteration''' :: Int -> Int -> Int -> Int -> Int -> (Int, Int, Int, Int)
iteration''' !cp !cv !ss !zv 0 = (cp, cv, ss, zv)
iteration''' !cp !cv !ss !zv !count = iteration''' ncp ncv ss nzv (count - 1)
where
ncp = ((cp + ss) `mod` cv) + 1
nzv = if ncp == 1 then cv else zv
ncv = cv + 1
I think the implication is that this is the idiomatic way to write (some) performant code as well!
I have just tried rewriting some code, originally a short Javascript function, in Haskell. The original has 2 nested loops and the inner loop contains a check for equality against both loop counters:
function f(x, points){
var i, j;
var n = points.length;
var result = 0;
for(i=0; i<n; i++){
var xprod = 1;
for(j=0; j<n; j++){
if(j != i){
xprod *= (x - points[j][0]);
}
}
result += points[i][1] * xprod;
}
return result;
}
I was hoping to be able to simplify it in Haskell, but I couldn't figure out how get hold of the i and j values without effectively writing out every step of the original recursively. In Javascript Array.map passes the list position into the callback function as the second parameter, but it seems that map in Haskell doesn't do this. My current Haskell version looks awful to me as I'm passing in 2 copies of the array (one for each loop):
xproduct :: Int -> Int -> Double -> [(Double,Double)] -> Double
xproduct _ _ _ [] = 1
xproduct i j x (pt:todo)
| i == j = (xproduct i (j+1) x todo)
| otherwise = (xproduct i (j+1) x todo) * (x - (fst pt))
solvestep :: Int -> Double -> [(Double,Double)] -> [(Double,Double)] -> Double
solvestep _ _ _ [] = 0
solvestep i x pts (pt:todo) = ((snd pt) * xprod) + (solvestep (i+1) x pts todo)
where xprod = xproduct i 0 x pts
solve :: Double -> [(Double,Double)] -> Double
solve x points = solvestep 0 x points points
Is there a better way to do this?
I generally avoid using any indices at all, if possible. In this case, what you're really working with is: any one element of the list with all the other elements. No need to express that with index comparison, instead write a function that will give you a suitable look into the list:
pickouts :: [a] -> [(a,[a])]
pickouts [] = []
pickouts (x:xs) = (x,xs) : (second (x:) <$> pickouts xs)
Then, the actual computation becomes just
f :: Double -> [(Double,Double)] -> Double
f x points = sum [q * product [x-p | (p,_)<-ps] | ((_,q),ps) <- pickouts points]
I was studying references in SML.
I wrote the following code:
let
val f = (fn (s) => s := ref((!(!s)) + 2))
val x = ref (5)
val y = ref x
in
(f y ; !x)
end;
I'm trying to get to val it = 7 : int, although my program prints val it = 5 : int. I can't understand why. I am sure the problem is in the f function but can't understand why.
What I'm trying to do: f function should update the argument y to be ref(ref(7)) so x could be ref(7). but for some reason it doesn't work. What is the problem?
Updating y to point to a new ref does not update x. There's a new reference created during the call to f, let's call it z. Before the call we have:
x -> 5
y -> x
where -> is "points to". After the call it is:
x -> 5
y -> z
z -> 7
Edit: One possible way to actually update x is by defining f as follows:
val f = fn r => !r := 7
When invoking f y, this updates the reference pointed to by y, which is x. But whether that is the "right" solution depends on what you actually want to achieve.
As Andreas Rossberg suggests, val f = fn r => !r := 7 could be one way to update the int of an int ref ref to 7. But instead of 7 you could write anything. If, instead, you want to increase by two the int being pointed indirectly to, a hybrid between your attempt and Andreas'es suggestion could be
fun f r = !r := !(!r) + 2
Here, !r := ... means "dereference r to get the int ref it points to, and update that int ref so that it instead points to ...", and !(!r) + 2 means "dereference r twice to get the int it indirectly points to, and add two to it." At this point, you have not changed what r points to (like you do with s := ref ...), and you're using the value it points to indirectly using the double-dereference !(!r).
A test program for this could be:
val x = ref 5
val y = ref x
fun f r = !r := !(!r) + 2
fun debug str =
print ( str ^ ": x points to " ^ Int.toString (!x) ^ " and "
^ "y points indirectly to " ^ Int.toString (!(!y)) ^ ".\n" )
val _ = debug "before"
val _ = f y
val _ = debug "after"
Running this test program yields:
before: x points to 5 and y points indirectly to 5.
after: x points to 7 and y points indirectly to 7.
It happens quite often that it is costly to calculate a property from a value. So it would be better to be able to store the property once it is calculated. I am wondering how to code this properly.
Let's take an example. Assume we have a type integer, and very often we need to calculate prime factors of a value of such type (let's assume the prime factors of a negative integer is None):
module I =
struct
type t = C of int
type pf = (int list) option
let calculate_prime_factors (x: t) : pf =
(* a costly function to calculate prime factors *)
... ...
let get_prime_factors (x: t) : pf =
calculate_prime_factors x
end
let () =
let v = I.C 100 in
let pf_1 = I.get_prime_factors v in
let pf_2 = I.get_prime_factors v in
let pf_3 = I.get_prime_factors v in
...
At the moment, get_prime_factors just calls calculate_prime_factors, as a consequence, all the calculations of pf_1, pf_2, pf_3 are time consuming. I would like to have a mechanism to enable storing prime factors inside the module, so that as long as the integer does not change, the second and third times of get_prime_factors just read what have been stored.
Does anyone know how to modify the module I to achieve this?
It is possible that we need references to make this mechanism possible (eg, let vr = ref (I.C 100) in ...). It is OK for me to use references. But I don't know how to trigger automatically calculate_prime_factors if the hold value (ie, !vr) is changed.
What you want to do is memoization, no ?
You could try this :
module I =
struct
type t = C of int
type pf = (int list) option
let calculate_prime_factors (x: t) : pf =
(* a costly function to calculate prime factors *)
... ...
module HI = Hashtbl.Make (struct
type t = C of int
let equal = (=)
let hash (C x) = x
end)
let get_prime_factors =
let h = Hashtbl.create 17 in
fun x ->
try Hashtbl.find h x
with
Not_found -> let pf = calculate_prime_factors x in
Hashtbl.add h x pf;
pf
end
let () =
let v = I.C 100 in
let pf_1 = I.get_prime_factors v in
let pf_2 = I.get_prime_factors v in
let pf_3 = I.get_prime_factors v in
...
You could adapt it for negative integers (with exceptions, for example, which is better than options) but I hope you get the idea.
Looks like, that you're looking for this solution:
module I = struct
type t = {
c : int;
mutable result : int option;
}
let create c = {c; result = None}
let calculate_prime_factors t = match t.result with
| Some r -> r
| None ->
let r = do_calculate t.c in
t.result <- Some r;
r
end
This is called memoizing. And this particular example can be solved even easier, with Lazy computations.
module I = struct
type t = int Lazy.t
let create c = lazy (do_calculate c)
let calculate_prime_factors = Lazy.force
end
I would do the following :
let get_prime_factors x =
match get x with
| None ->
let res = calculate_prime_factors x
in
begin
set x res ;
res
end
| Some res -> res
;;
You need a mutable data structure accessed by get and set. For instance, with a reference on a list (but you may prefer a hashtable) :
let my_storage = ref [] (* or something mutable *)
let get x =
if List.mem_assoc x !my_storage
then Some (List.assoc x !my_storage)
else None
let set x r =
my_storage := (x,r) :: !my_storage ;;
You can also use exceptions instead of the option type (None and Some _).
I am having trouble with the following exercise:
I must make a function named addDigit, which takes two Int's, the second one being between 0 and 9, and return an Int that is the first Int followed by the second one.
Example:
input: addDigit (-123) 4
output: -1234
what I have tried is the following :
addDigit :: Int -> Int -> Int
addDigit x y = x ++ y
I get it doesn't work because the ++ keyword only works with strings, chars and lists (i think), and this is supposed to be solved in a simple way without changing the Int's to Strings or any sort of other variables, but i have no clue at all on how to do it.
You are trying to solve the problem graphically (thinking of the integers as strings), you want to treat it as a numerical problem. For positive values, appending a digit is accomplished by the following function.
addDigitPositive a b = 10 * a + b
This will unfortunately not work if a < 0. Under those circumstances we would have to subtract b. We can incorporate this functionality easily with function guards.
addDigit a b | a < 0 = a * 10 - b
| otherwise = a * 10 + b
Or you could solve it graphically, by converting the numbers to strings using show and then concatenating them with (++):
addDigit :: Int -> Int -> String
addDigit x y = (show x) ++ (show y)
Now, if you still want an Int as the output, you can convert the string to an Int using read:
addDigit :: Int -> Int -> Int
addDigit x y = read ((show x) ++ (show y))
As you can see, there is more than one way to skin a cat.
I hope this helps.