I'm trying to write a function in SML to flip alternate elements of a list. Here's my function:
fun flipAlternate(nil) = nil
| flipAlternate([x]) = x
| flipAlternate(x::y::xs) = y::x::flipAlternate(xs);
When I go to use my file (Ullman.sml) in the interactive interpreter, I get this compilation error:
- use "Ullman.sml";
[opening Ullman.sml]
Ullman.sml:5.31-5.54 Error: operator and operand don't agree [circularity]
operator domain: 'Z list * 'Z list list
operand: 'Z list * 'Z list
in expression:
x :: flipAlternate xs
So SML is saying it requires a list of lists of integers but I'm only giving it a pair of lists of integers?
I'm a bit lost here so any help would be much appreciated.
Thanks,
bclayman
Your second case is wrong; you want
fun flipAlternate(nil) = nil
| flipAlternate([x]) = [x]
| flipAlternate(x::y::xs) = y::x::flipAlternate(xs);
SML is looking at the second case and concluding
flipAlternate :: 'z list list -> 'z list
which isn't compatible with the recursion in your third case.
Edit: It knows the result is a list from the first case, and concludes the argument has one more list than the result from the second case.
I've been learning Erlang and tried completing some practise functions. I struggled making one function in particular and think it might be due to me not thinking "Erlang" enough.
The function in question takes a list and a sublist size then produces a list of tuples containing the number of elements before the a sublist, the sublist itself and the number of elements after the sublist. For example
sublists(1,[a,b,c])=:=[{0,[a],2}, {1,[b],1}, {2,[c],0}].
sublists(2,[a,b,c])=:=[{0,[a,b],1}, {1,[b,c],0}].
My working solution was
sublists(SubListSize, [H | T]) ->
Length = length(1, T),
sublists(SubListSize, Length, Length-SubListSize, [H|T], []).
sublists(_, _, -1, _, Acc) -> lists:reverse(Acc);
sublists(SubSize, Length, Count, [H|T], Acc) ->
Sub = {Length-SubSize-Count, grab(SubSize, [H|T],[]),Count},
sublists(SubSize, Length, Count-1, T, [Sub|Acc]).
length(N, []) -> N;
length(N, [_|T]) -> length(N+1, T).
grab(0, _, Acc) -> lists:reverse(Acc);
grab(N, [H|T], Acc) -> grab(N-1, T, [H|Acc]).
but it doesn't feel right and I wondered if there was a better way?
There was an extension that asked for the sublists function to be re-implemented using a list comprehension. My failed attempt was
sublist_lc(SubSize, L) ->
Length = length(0, L),
Indexed = lists:zip(L, lists:seq(0, Length-1)),
[{I, X, Length-1-SubSize} || {X,I} <- Indexed, I =< Length-SubSize].
As I understand it, list comprehensions can't see ahead so I was unable to use my grab function from earlier. This again makes me thing there must be a better way of solving this problem.
I show a few approaches below. All protect against the case where the requested sublist length is greater than the list length. All use functions from the standard lists module.
The first one uses lists:split/2 to capture each sublist and the length of the remaining tail list, and uses a counter C to keep track of how many elements precede the sublist. The length of the remaining tail list, named Rest, gives the number of elements that follow each sublist.
sublists(N,L) when N =< length(L) ->
sublists(N,L,[],0).
sublists(N,L,Acc,C) when N == length(L) ->
lists:reverse([{C,L,0}|Acc]);
sublists(N,[_|T]=L,Acc,C) ->
{SL,Rest} = lists:split(N,L),
sublists(N,T,[{C,SL,length(Rest)}|Acc],C+1).
The next one uses two lists of counters, one indicating how many elements precede the sublist and the other indicating how many follow it. The first is easily calculated by simply counting from 0 to the length of the input list minus the length of each sublist, and the second list of counters is just the reverse of the first. These counter lists are also used to control recursion; we stop when each contains only a single element, indicating we've reached the final sublist and can end the recursion. This approach uses the lists:sublist/2 call to obtain all but the final sublist.
sublists(N,L) when N =< length(L) ->
Up = lists:seq(0,length(L)-N),
Down = lists:reverse(Up),
sublists(N,L,[],{Up,Down}).
sublists(_,L,Acc,{[U],[D]}) ->
lists:reverse([{U,L,D}|Acc]);
sublists(N,[_|T]=L,Acc,{[U|UT],[D|DT]}) ->
sublists(N,T,[{U,lists:sublist(L,N),D}|Acc],{UT,DT}).
And finally, here's a solution based on a list comprehension. It's similar to the previous solution in that it uses two lists of counters to control iteration. It also makes use of lists:nthtail/2 and lists:sublist/2 to obtain each sublist, which admittedly isn't very efficient; no doubt it can be improved.
sublists(N,L) when N =< length(L) ->
Up = lists:seq(0,length(L)-N),
Down = lists:reverse(Up),
[{U,lists:sublist(lists:nthtail(U,L),N),D} || {U,D} <- lists:zip(Up,Down)].
Oh, and a word of caution: your code implements a function named length/2, which is somewhat confusing because it has the same name as the standard length/1 function. I recommend avoiding naming your functions the same as such commonly-used standard functions.
We want to find the largest value in a given nonempty list of integers. Then we have to compare elements in the list. Since data
values are given as a sequence, we can do comparisons from the
beginning or from the end of the list. Define in both ways. a)
comparison from the beginning b) comparison from the end (How can we
do this when data values are in a list?) No auxiliary functions.
I've been playing around a lot with recursive functions, but can't seem to figure out how to compare two values in the list.
fun listCompare [] = 0
| listCompare [x] = x
| listCompare (x::xs) = listCompare(xs)
This will break the list down to the last element, but how do I start comparing and composing the list back up?
You could compare the first two elements of a given list and keep the larger element in the list and drop the other. Once the list has only one element, then you have the maximum. In functional pseudocode for a) it looks roughly like so:
lmax [] = error "empty list"
lmax [x] = x
lmax (x::y::xs) =
if x > y then lmax (x::xs)
else lmax (y::xs)
For b) you could reverse the list first.
This is what the foldl (or foldr) function in the SML list library is for :
foldl : ((`a * `b) -> `b) -> `b -> `a list -> `b
You can simply add an anonymous function to compare the current element against the accumulator :
fun lMax l =
foldl (fn (x,y) => if x > y then x else y) (nth l 0) l
The nth function simply takes the int list : l and an int : 0 to return the first element in the list. As lists in SML are written recursively as : h :: t, retrieving the first element is an O(1) operation, and using the foldl function greatly increases the elegance of code. The whole point of having a functional language is to define abstractions to pass around anonymous functions as higher-order functions and re-use the abstract type definitions with concrete functions.
I got an implementation for append function in OCaml, but it seems confused to me
let rec append = function
| [] -> fun y -> y
| h :: t -> fun y -> h :: (append t y)
What is the purpose of the fun y in this case ?
The type of append is 'a list -> 'a list -> 'a list. You can look at this as a function that takes two lists and returns a list. But (as is idiomatic in OCaml) the function is defined using currying. So at the basic level, append takes a first list and returns a function of type 'a list -> 'a list. The returned function takes the second list and prefixes the first list to it (returning the result).
The value fun y -> y is the function that append returns when the first list is empty. If you think about it, this makes sense. If the first list is empty, the second list will be returned unchanged. In other words, the returned function is no different at all from an identity function (specialized for applying to lists).
The second case returns the value fun y -> h :: (append t y). This is similar, but a little more complicated. The returned function needs to do some actual appending. It does this by (recursively) appending the supplied second list (y) to the tail of the first list (t), then adding the head of the first list (h) to the front of that.
If you don't like the fun, you can rewrite the function like this
let rec append x y = match x with
| [] -> y
| h :: t -> h :: append t y
In a Clojure book, I found a map function with 3 args:
(Map vector (iterate inc 0) coll)
What is the vector doing? How is it that this function accepts 3 args instead of the standard 2?
The map function accepts a variable number of arguments. The required first argument is a function, and then you can pass any number of collections after. When more than one collection is passed, the corresponding element from each collection will be passed as an argument to the function (e.g. if you pass one collection, the function will receive one argument, and if you pass three collections, it will receive three arguments).
As for vector, it does the same thing the vector function usually does — make a vector out of its arguments. For example, (vector 1 100 1000) gives [1 100 1000]. In this case, its arguments will be the nth elements of two collections:
An infinite sequence of integers starting at zero
Whatever is in coll
In effect, this transforms each item in coll into a vector containing the item's index followed by the item. So if coll is [a b c], for example, it will give you ([0 a] [1 b] [2 c]).