What exactly does this Standard ML code do? - ml

I'm reading Chris Okasaki's purely functional data structures, and there's one example I am having trouble with. It is located here. In particular, I don't understand how the rotate and exec functions work:
fun rotate($Nil, y::_, a) = $Cons (y, a)
| rotate ($Cons (x, xs), y :: ys, a) =
$Cons(x, rotate (xs, ys, $Cons (y, a)))
fun exec (f, r, $Cons (X, s)) = (f, r, s)
| exec (f, r, $Nil) = let val f' = rotate (f, r, $Nil) in (f', [], f') end
Could someone put this in stupid-people terms? I'm still learning my ML-based languages. :-)

That doesn't look like the Standard ML I learned (with $ characters in front of data constructors) but perhaps things have changed. Anyhow:
First of all there's a small typo on line 2 of rotate, you added a comma after $Cons
Basically rotate takes a tuple of three lists and assembles them in the order: first one ++ (reverse of second one) ++ third one. But it does this linearly by pulling elements from both list 1 and list 2 at the same time. The head of List 1 is cons'd to the final result (a o(1) operation). But the tail of list 2 is passed as an argument to the recursive call, and its head is cons'd onto the third argument, which amounts to reversing it.
That third argument is basically acting as an accumulator. In functional programming using an accumulator as an argument like that can be a trick for avoiding more expensive computations.
I admit to not understanding the purpose of exec. What's the context?

This doesn't explain the whole thing, but note that in fun rotate($Nil, y::_, a), the y::_ is a pattern that matches a list wherein you label the head of the list (first element) as y and the tail of the list (every item after the first element) as _. _ acts as a wildcard pattern.
Check out SML on Wikipedia, specifically the Mergesort implementation, for more use of :: patterns and _.

Related

Haskell : Increment index in a loop

I have a function that calculates f(n) in Haskell.
I have to write a loop so that it will start calculating values from f(0) to f(n), and will every time compare the value of f(i) with some fixed value.
I am an expert in OOP, hence I am finding it difficult to think in the functional way.
For example, I have to write something like
while (number < f(i))
i++
How would I write this in Haskell?
The standard approach here is
Create an infinite list containing all values of f(n).
Search this list until you find what you're after.
For example,
takeWhile (number <) $ map f [0..]
If you want to give up after you reach "n", you can easily add that as a separate step:
takeWhile (number <) $ take n $ map f [0..]
or, alternatively,
takeWhile (number <) $ map f [0 .. n]
You can do all sorts of other filtering, grouping and processing in this way. But it requires a mental shift. It's a bit like the difference between writing a for-loop to search a table, versus writing an SQL query. Think about Haskell as a bit like SQL, and you'll usually see how to structure your code.
You can generate the list of the is such that f i is larger than your number:
[ i | i<-[0..] , f i > number ]
Then, you can simply take the first one, if that's all you want:
head [ i | i<-[0..] , f i > number ]
Often, many idiomatic loops in imperative programming can be rephrased as list comprehensions, or expressed through map, filter, foldl, foldr. In the general case, when the loop is more complex, you can always exploit recursion instead.
Keep in mind that a "blind" translation from imperative to functional programming will often lead to non-idiomatic, hard-to-read code, as it would be the case when translating in the opposite direction. Still, I find it relieving that such translation is always possible.
If you are new to functional programming, I would advise against learning it by translating what you know about imperative programming. Rather, start from scratch following a good book (LYAH is a popular choice).
The first thing that's weird from a functional approach is that it's unclear what the result of your computation is. Do you care about the final result of f (i)? Perhaps you care about i itself. Without side effects everything neends to have a value.
Let's assume you want the final value of the function f (i) as soon as some comparison fails. You can simulate your own while loops using recursion and guards!
while :: Int -> Int -> (Int -> Int) -> Int
while start number f
| val >= number = val
| otherwise = while (start + 1) number f
where
val = f start
Instead of explicit recursion, you can use until e.g.
findGreaterThan :: (Int -> Int) -> Int -> Int -> (Int, Int)
findGreaterThan f init max = until (\(v, i) -> v >= max) (\(v, i) -> (f v, i + 1)) (init, 0)
this returns a pair containing the first value to fail the condition and the number of iterations of the given function.

Smart and Fast Indexing of multi-dimensional array with R

This is another step of my battle with multi-dimensional arrays in R, previous question is here :)
I have a big R array with the following dimensions:
> data = array(..., dim = c(x, y, N, value))
I'd like to perform a sort of bootstrap comparing the mean (see here for a discussion about it) obtained with:
> vmean = apply(data, c(1,2,3), mean)
With the mean obtained sampling the N values randomly with replacement, to explain better if data[1,1,,1] is equals to [v1 v2 v3 ... vN] I'd like to replace it with something like [v_k1 v_k2 v_k3 ... v_kN] with k values sampled with sample(N, N, replace = T).
Of course I want to AVOID a for loop. I've read this but I don't know how to perform an efficient indexing of this array avoiding a loop through x and y.
Any ideas?
UPDATE: the important thing here is that I want a different sample for each sample in the fourth (value) dimension, otherwise it would be simple to do something like:
> dataSample = data[,,sample(N, N, replace = T), ]
Also there's the compiler package which speeds up for loops by using a Just In Time compiler.
Adding thes lines at the top of your code enables the compiler for all code.
require("compiler")
compilePKGS(enable=T)
enableJIT(3)
setCompilerOptions(suppressAll=T)

Array in Haskell

How is an array created in haskell using the constructor array? I mean, does it create the first element and so on? In that case how does it read the associated list?
For example if we consider the following two programs:-
ar :: Int->(Array Int Int)
ar n = array (0,(n-1)) (((n-1),1):[(i,((ar n)!(i+1))) | i<-[0..(n-2)]])
ar :: Int->(Array Int Int)
ar n = array (0,(n-1)) ((0,1):[(i,((ar n)!(i-1))) | i<-[1..(n-1)]])
Will these two have different time complexity?
That depends on the implementation, but in a reasonable implementation, both have the same complexity (linear in the array size).
In GHC's array implementation, if we look at the code
array (l,u) ies
= let n = safeRangeSize (l,u)
in unsafeArray' (l,u) n
[(safeIndex (l,u) n i, e) | (i, e) <- ies]
{-# INLINE unsafeArray' #-}
unsafeArray' :: Ix i => (i,i) -> Int -> [(Int, e)] -> Array i e
unsafeArray' (l,u) n#(I# n#) ies = runST (ST $ \s1# ->
case newArray# n# arrEleBottom s1# of
(# s2#, marr# #) ->
foldr (fill marr#) (done l u n marr#) ies s2#)
{-# INLINE fill #-}
fill :: MutableArray# s e -> (Int, e) -> STRep s a -> STRep s a
-- NB: put the \s after the "=" so that 'fill'
-- inlines when applied to three args
fill marr# (I# i#, e) next
= \s1# -> case writeArray# marr# i# e s1# of
s2# -> next s2#
we can see that first a new chunk of memory is allocated for the array, that is then sequentially filled with arrEleBottom (which is an error call with message "undefined array element"), and then the elements supplied in the list are written to the respective indices in the order they appear in the list.
In general, since it is a boxed array, what is written to the array on construction is a thunk that specifies how to compute the value when it is needed (explicitly specified values, like the literal 1 in your examples, will result in a direct pointer to that value written to the array).
When the evaluation of such a thunk is forced, it may force also the evaluation of further thunks in the array - if the thunk refers to other array elements, like here. In the specific examples here, forcing any thunk results in forcing all thunks later resp. earlier in the array until the end with the entry that doesn't refer to another array element is reached. In the first example, if the first array element that is forced is the one at index 0, that builds a thunk of size proportional to the array length that is then reduced, so forcing the first array element then has complexity O(n), then all further elements are already evaluated, and forcing them is O(1). In the second example, the situation is symmetric, there forcing the last element first incurs the total evaluation cost. If the elements are demanded in a different order, the cost of evaluating all thunks is spread across the requests for different elements, but the total cost is the same. The cost of evaluating any not-yet-evaluated thunk is proportional to its distance from the next already evaluated thunk, and includes evaluating all thunks in between.
Since array access is constant time (except for cache effects, but those should not make a difference if you fill the array either forward or backward, they could make a big difference if the indices were in random order, but that still wouldn't affect time complexity), both have the same complexity.
Note however, that your using ar n to define the array elements carries the risk of multiple arrays being allocated (if compiled without optimisations, GHC does that - just tested: even with optimisations that can happen). To make sure that only one is constructed, make it
ar n = result
where
result = array (0,n-1) (... result!index ...)

Plese write a solution for a prolog task

I have a matrix M x N, I need to switch places of the elements with indexed [1,N] and [M,N].
Update
I am really new to Prolog, here is my solution that returns false :(
main([FirstRow|Tail],X):-
last(FirstRow, A),
last(Tail, LastRow),
last(LastRow, B),
skipLastItem(FirstRow,FirstRowWithoutA),
skipLastItem(LastRow,LastRowWithoutB),
append(FirstRowWithoutA,[B],FirstRowNew),
append(LastRowWithoutB,[A],LastRowNew),
assign([FirstRowNew],X),
skipLastItem(Tail,Middle),
appendAllElements(Middle,X),
append(X,LastRowNew,X).
appendAllElements([X|Tail],List):-
append(List,X,NewList),
appendAllElements(Tail,NewList).
appendAllElements([],_).
assign(Item,Item).
skipLastItem([_],[ ]) :- !.
skipLastItem([H|T],[H|S]) :-
skipLastItem(T,S).
This sounds like homework, so I'm going to be a bit vague here...
Start with the simpler problem of replacing one value in a list. Write a recursive predicate
swap_list(X,N,A,B,Y)
which should be read as "for a list X, at position N, removing the value A and replacing it with B gives the list Y".
Now we can extend this to the case of matrices. Write a second recursive predicate
swap_matrix(X,M,N,A,B,Y)
which should be read as "for a matrix X, at position (M,N), removing element A and replacing it with B gives the matrix Y". The base case of this recursion, where M=0, will contain a call to swap_list.
Now, you can swap two positions (M1,N1) and (M2,N2) with the following:
swap(X,M1,N1,M2,N2,Y) :-
swap_matrix(X,M1,N1,A,B,Z),
swap_matrix(Z,M2,N2,B,A,Y).
Note that we insert B into the matrix Z before we even know what it is - B isn't assigned a value until the second swap_matrix call.

Iterating with respect to two variables in haskell

OK, continuing with my solving of the problems on Project Euler, I am still beginning to learn Haskell and programming in general.
I need to find the lowest number divisible by the numbers 1:20
So I started with:
divides :: Int -> Int -> Bool
divides d n = rem n d == 0
divise n a | divides n a == 0 = n : divise n (a+1)
| otherwise = n : divise (n+1) a
What I want to happen is for it to keep moving up for values of n until one magically is evenly divisible by [1..20].
But this doesn't work and now I am stuck as from where to go from here. I assume I need to use:
[1..20]
for the value of a but I don't know how to implement this.
Well, having recently solved the Euler problem myself, I'm tempted to just post my answer for that, but for now I'll abstain. :)
Right now, the flow of your program is a bit chaotic, to sound like a feng-shui person. Basically, you're trying to do one thing: increment n until 1..20 divides n. But really, you should view it as two steps.
Currently, your code is saying: "if a doesn't divide n, increment n. If a does divide n, increment a". But that's not what you want it to say.
You want (I think) to say "increment n, and see if it divides [Edit: with ALL numbers 1..20]. If not, increment n again, and test again, etc." What you want to do, then, is have a sub-test: one that takes a number, and tests it against 1..20, and then returns a result.
Hope this helps! Have fun with the Euler problems!
Edit: I really, really should remember all the words.
Well, as an algorithm, this kinda sucks.
Sorry.
But you're getting misled by the list. I think what you're trying to do is iterate through all the available numbers, until you find one that everything in [1..20] divides. In your implementation above, if a doesn't divide n, you never go back and check b < a for n+1.
Any easy implementation of your algorithm would be:
lcmAll :: [Int] -> Maybe Int
lcmAll nums = find (\n -> all (divides n) nums) [1..]
(using Data.List.find and Data.List.all).
A better algorithm would be to find the lcm's pairwise, using foldl:
lcmAll :: [Int] -> Int
lcmAll = foldl lcmPair 1
lcmPair :: Int -> Int -> Int
lcmPair a b = lcmPair' a b
where lcmPair' a' b' | a' < b' = lcmPair' (a+a') b'
| a' > b' = lcmPair' a' (b + b')
| otherwise = a'
Of course, you could use the lcm function from the Prelude instead of lcmPair.
This works because the least common multiple of any set of numbers is the same as the least common multiple of [the least common multiple of two of those numbers] and [the rest of the numbers]
The function 'divise' never stops, it doesn't have a base case. Both branches calls divise, thus they are both recursive. Your also using the function divides as if it would return an int (like rem does), but it returns a Bool.
I see you have already started to divide the problem into parts, this is usually good for understanding and making it easier to read.
Another thing that can help is to write the types of the functions. If your function works but your not sure of its type, try :i myFunction in ghci. Here I've fixed the type error in divides (although other errors remains):
*Main> :i divise
divise :: Int -> Int -> [Int] -- Defined at divise.hs:4:0-5
Did you want it to return a list?
Leaving you to solve the problem, try to further divide the problem into parts. Here's a naive way to do it:
A function that checks if one number is evenly divisible by another. This is your divides function.
A function that checks if a number is dividable by all numbers [1..20].
A function that tries iterates all numbers and tries them on the function in #2.
Here's my quick, more Haskell-y approach, using your algorithm:
Prelude> let divisibleByUpTo i n = all (\x -> (i `rem` x) == 0) [1..n]
Prelude> take 1 $ filter (\x -> snd x == True) $ map (\x -> (x, divisibleByUpTo x 4)) [1..]
[(12,True)]
divisibleByUpTo returns a boolean if the number i is divisible by every integer up to and including n, similar to your divides function.
The next line probably looks pretty difficult to a Haskell newcomer, so I'll explain it bit-by-bit:
Starting from the right, we have map (\x -> (x, divisibleByUpTo x 4)) [1..] which says for every number x from 1 upwards, do divisibleByUpTo x 4 and return it in a tuple of (x, divisibleByUpTo x 4). I'm using a tuple so we know which number exactly divides.
Left of that, we have filter (\x -> snd x == True); meaning only return elements where the second item of the tuple is True.
And at the leftmost of the statement, we take 1 because otherwise we'd have an infinite list of results.
This will take quite a long time for a value of 20. Like others said, you need a better algorithm -- consider how for a value of 4, even though our "input" numbers were 1-2-3-4, ultimately the answer was only the product of 3*4. Think about why 1 and 2 were "dropped" from the equation.

Resources