Reversing a list in SML - list

fun reverse ( [] ) = ( [] )
| reverse (x::xs) = reverse (xs) :: [x]
why my this function of reversing a list is not working

Your function has type 'a list -> 'a list. :: has type 'a -> 'a list -> 'a list. Thus you can't pass the result of calling reverse as the first argument to ::.
You could use # as suggested by JRose because that has type 'a list -> 'a list -> 'a list and will concatenate the two lists but that is inefficient compared to ::. # is O(n). Using it makes reverse have O(n^2) runtime efficiency.
Instead, let's use a tail-recursive helper function to build up an accumulator list in reverse order using ::, then return that. Because :: is O(1), this has O(n) runtime efficiency which is much better.
fun reverse lst =
let
fun aux [] acc = acc
| aux (x::xs) acc = aux xs (x :: acc)
in
aux lst []
end
Consider reversing [1, 2, 3]:
reverse [1, 2, 3]
aux [1, 2, 3] []
aux [2, 3] [1]
aux [3] [2, 1]
aux [] [3, 2, 1]
[3, 2, 1]
Further reading on the efficiency of # and ::. The link talks about OCaml, but the core principles are the same in SML.

Related

recursive ML function unnest that accepts only a value of type 'a NestedList and return a list

Here is an example
Examples:
- unnest;
val it = fn : 'a NestedList -> 'a list
(* [1,2,3] *)
- unnest(List [(Atom 1), (Atom 2), (Atom 3)]);
val it = [1,2,3] : int list
I was give
datatype 'a NestedList =
Nil
| Atom of 'a
| List of 'a NestedList list;
What I have so far
fun unnest(Nil) = []
| unnest(Atom(x)) = [x]
| unnest(List(x::xs)) = unnest(x);
which only gives the head part of the list and I do not know how to get to the rest of list.
I understand there is a way using concat and map and fn but is there without using library function?
Applying unnest to a NestedList value is meant to yield a plain old list. So we know the type of this function must be:
'a NestedList -> 'a list
When we apply unnest to a List, we need to recursively apply it to each element in that contained list.
There are two issues with your function.
It doesn't account for an empty list in the pattern-matching.
It only acts on the first item in a non-empty list.
If we map unnest to each element in that contained list, we'll get a list of lists. This isn't what we ultimately want, but we can work with it.
fun unnest(Nil) = []
| unnest(Atom(x)) = [x]
| unnest(List(lst)) = map unnest lst
The above won't compile because the final case yields an 'a list list. How can we turn a list of lists into just a list?
We can concatenate two lists with the # operator, and that means we can fold this over the lists to get a flattened list.
fun unnest(Nil) = []
| unnest(Atom(x)) = [x]
| unnest(List(lst)) = foldl op# [] (map unnest lst)
Evaluating unnest(List [(Atom 1), (Atom 2), (Atom 3)]) now gets us [3, 2, 1]. This is reversed because of the order in which foldl sends arguments to op#. If we write an anonymous function we can correct this.
fun unnest(Nil) = []
| unnest(Atom(x)) = [x]
| unnest(List(lst)) = foldl (fn (x, i) => i # x) [] (map unnest lst)

Defining inits function recursively

In Data.List module there's inits function that turns for example, [1,2,3,4] -> [[],[1],[1,2],[1,2,3],[1,2,3,4]]
I'm trying to define similar function using recursion, however I can't think of a way doing in correct order. The closest I have gotten is the list backwards, result = [[],[4],[3,4],[2,3,4],[1,2,3,4]]:
inits' :: [Int] -> [[Int]]
inits' [] = [[]]
inits' (x:xs) = inits' xs ++ [(x:xs)]
I'm not exactly sure how I could create a list by appending one element at time in the correct order? Could someone point in right direction, or is it not possible to do via recursion?
The easiest thing to try for such a function is just looking at the desired result and “reverse-pattern-matching” on the RHS of the function equation.
You already have that with
inits' [] = [[]]
Now with inits (x:xs), for example inits (1:[2,3,4]), you know that the result should be [[],[1],[1,2],[1,2,3],[1,2,3,4]], which matches the pattern []:_. So
inits' (x:xs) = [] : _
Now, the simplest recursion would be to just call inits' again on xs, like
inits' (x:xs) = [] : inits' xs
however, that doesn't give the correct result: assuming the recursive call works correctly, you have
inits' (1:[2,3,4]) = [] : [[],[2],[2,3],[2,3,4]]
= [[],[],[2],[2,3],[2,3,4]]
The 1 is completely missing, obviously, because we didn't actually use it in the definition. We need to use it, in fact it should be prepended before all of the list-chunks in the recursive result. You can do that with map.
We can prepend the data of all the remaining inits, like for example:
inits' :: [a] -> [[a]]
inits' [] = [[]]
inits' (x:xs) = [] : map (x:) (inits' xs)
As a basecase we return a singleton list with an empty list when the input is an empty list.
In the recursive case, we first yield the empty list, followed by the inits' of the tail of the list, but all these elements are prepended with x (with map (x:)).
Then we have:
Prelude> inits' [1,4,2,5]
[[],[1],[1,4],[1,4,2],[1,4,2,5]]
Since (not in evaluation order):
inits' [1,4,2,5]
-> [] : map (1:) (inits' [4,2,5])
-> [] : map (1:) ([] : map (4:) (inits' [2,5]))
-> [] : map (1:) ([] : map (4:) ([] : map (2:) (inits' [5])))
-> [] : map (1:) ([] : map (4:) ([] : map (2:) ([] : map (5:) (inits' []))))
-> [] : map (1:) ([] : map (4:) ([] : map (2:) ([] : map (5:) [[]])))
-> [] : map (1:) ([] : map (4:) ([] : map (2:) ([] : [[5]])))
-> [] : map (1:) ([] : map (4:) ([] : map (2:) [[],[5]]))
-> [] : map (1:) ([] : map (4:) ([] : [[2],[2,5]]))
-> [] : map (1:) ([] : map (4:) [[],[2],[2,5]])
-> [] : map (1:) ([] : [[4],[4,2],[4,2,5]])
-> [] : map (1:) [[],[4],[4,2],[4,2,5]]
-> [] : [[1],[1,4],[1,4,2],[1,4,2,5]]
-> [[],[1],[1,4],[1,4,2],[1,4,2,5]]
I think you should change your function definition from:
inits' :: [Int] -> [[Int]]
to:
inits' :: [a] -> [[a]]
Since inits from Data.List is of type [a] -> [[a]], and it doesn't care whats actually in the list. It needs to be polymorphic and accept a list of any type.
Furthermore, since others have shown the most straightforward recursive approach, you can also use foldr here.
Here is the base code:
inits' :: [a] -> [[a]]
inits' = foldr (\x acc -> [] : (map (x:) acc)) [[]]
Where [[]] is the base case, just like in your function. For the actual recursive part, here is how it works with the call inits' [1, 2, 3, 4]:
Starts folding from the right at value 4, and creates [[], [4]]
Now on value 3, and creates [[], [3], [3, 4]
Now on value 2, and creates [[], [2], [2, 3], [2, 3, 4]]
Now on value 1, and creates [[], [1], [1, 2], [1, 2, 3], [1, 2, 3, 4]]
Which gives the final nested list required, similarily to the function call:
*Main> inits' [1,2,3,4]
[[],[1],[1,2],[1,2,3],[1,2,3,4]]
From the behavior described above, you just need to focus on [] : (map (x:) acc), where you map the current value x being folded into your accumulated list acc, while also prepending an empty list on each fold.
If you still have trouble understanding foldr, you can look at this minimal example of how the folding performs from the right:
foldr f x [a, b, c] = a `f` (b `f` (c `f` x))
and How does foldr work?

Reverse a custom nested list in Haskell

I am working on trying to reverse a nested list in Haskell. I am aware that nested lists are not a thing in Haskell so I defined one:
data NestedList a = Elem a | SubList [NestedList a]
I also have a flatten function:
flatten :: NestedList a -> [a]
flatten (Elem x) = [x]
flatten (SubList x) = concatMap flatten x
Now I wish to write my reverse function. The function is defined as:
myreverse :: NestedList a -> NestedList a
Which I think makes sense because I'm just rearranging the elements within the list.
I understand how to write a basic reverse function, and I also know that for Haskell's standard lists reverse is already defined.
My question is: how do I deal with the case where the head of the list is also a list? What I know needs to happen is that I reverse the head of the list and put it back onto the reverse of the tail. But how to achieve this?
why not this way
rev :: NestedList a -> NestedList a
rev (Elem a) = Elem a
rev (SubList xs) = SubList $ map rev $ reverse xs
if you add deriving (Show) to your data definition,
Prelude> rev $ SubList [Elem 1, SubList [Elem 2, Elem 3]]
SubList [SubList [Elem 3,Elem 2],Elem 1]
Prelude> rev $ SubList [Elem 1, SubList []]
SubList [SubList [],Elem 1]
Your nested list is actually a tree with elements at leavess:
SubList
/ \
SubList Elem 4
/ | \
Elem 1 Elem 2 Elem 3
So your myreverse would be a horizontal flip, i.e. recursive reverse of each list in SubList, as other answer points out.
The lesson here: Visualising data-structures helps to understand and implement actions on them.

haskell, is number in one list is within the range of a second list?

What is the best way to find out if a number in a list is within the range of a second list, using a Maybe data type?
What I have so far:
getElems :: [Int] -> [a] -> [Maybe a]
getElems [xs] ys
| head(tail[(xs)]) > head(tail[(ys)]) = [Nothing]
| otherwise = [Just xs]
It needs to return those elements that correspond to the positions specified. Depending on if a position is greater than the list size it returns Nothing, else Just value.
For example:
getElems [2,4] [1..10] ) [Just 3,Just 5]
getElems [2,4] [1..4] ) [Just 3,Nothing]
You can write an getElementByIndex which does that for a single list:
getElementByIndex :: Int -> [a] -> Maybe a
getElementByIndex n [] = Nothing
getElementByIndex n (x:xs) = if (n == 0)
then Just x
else getElementByIndex (n - 1) xs
And then just map it to get an answer:
getElems :: [Int] -> [a] -> [Maybe a]
getElems xs ys = map (\x -> getElementByIndex x ys) xs
Demo in ghci:
λ> getElems [2,4] [1..10]
[Just 3,Just 5]
λ> getElems [2,4] [1..4]
[Just 3,Nothing]

Creating tuples variations from a list - Haskell

I am a relative haskell newbie and am trying to create a list of tuples with an equation I named splits that arises from a single list originally, like this:
splits [1..4] --> [ ([1],[2,3,4]), ([1,2],[3,4]), ([1,2,3],[4]) ]
or
splits "xyz" --> [ ("x","yz"), ("xy","z") ]
Creating a list of tuples that take 1, then 2, then 3 elements, etc. I figured out I should probably use the take/drop functions, but this is what I have so far and I'm running into a lot of type declaration errors... Any ideas?
splits :: (Num a) => [a] -> [([a], [a])]
splits [] = error "shortList"
splits [x]
| length [x] <= 1 = error "shortList"
| otherwise = splits' [x] 1
where splits' [x] n = [(take n [x], drop n [x])] + splits' [x] (n+1)
The Haskell-y approach is to use the inits and tails functions from Data.List:
inits [1,2,3,4] = [ [], [1], [1,2], [1,2,3], [1,2,3,4] ]
tails [1,2,3,4] = [ [1,2,3,4], [2,3,4], [3,4], [4], [] ]
We then just zip these two lists together and drop the first pair:
splits xs = tail $ zip (inits xs) (tails xs)
or equivalently, drop the first element of each of the constituent lists first:
= zip (tail (inits xs)) (tail (tails xs))
splits [] = []
splits [_] = []
splits (x:xs) = ([x], xs) : map (\(ys, zs) -> (x:ys, zs)) (splits xs)
You have several mistakes.
You don't need to have Num a class for a.
use [] or [x] as pattern, but not a variable, use xs instead.
Use ++ instead of + for concatenating lists.
In our case use (:) to add list to value instead of ++.
Add stop for recursion, like additional variable maxn to splits'
splits :: [a] -> [([a], [a])]
splits [] = error "shortList"
splits xs
| lxs <= 1 = error "shortList"
| otherwise = splits' xs 1 lxs
where
lxs = length xs
splits' xs n maxn
| n > maxn = []
| otherwise = (take n xs, drop n xs) : splits' xs (n+1) maxn
There is a built in function that kind of does a part of what you want:
splitAt :: Int -> [a] -> ([a], [a])
which does what it looks like it would do:
> splitAt 2 [1..4]
([1,2],[3,4])
Using this function, you can just define splits like this:
splits xs = map (flip splitAt xs) [1..length xs - 1]