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

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)

Related

Return a list of all the even elements in the orginal list - how can I write this function without using recursion?

This function takes a list and returns a list of all the even elements from the original list. I'm trying to figure out how to do this using foldl, foldr, or map instead but I can't seem to figure it out.
fun evens [] = []
| evens (x::xs) =
if
x mod 2 = 0
then
x::evens(xs)
else
evens(xs);
Since you want fewer elements than you start with, map is out.
If you copy a list using both foldl and foldr,
- foldl (op ::) [] [1,2,3];
val it = [3,2,1] : int list
- foldr (op ::) [] [1,2,3];
val it = [1,2,3] : int list
you see that foldl reverses it, so foldr is a pretty natural choice if you want to maintain the order.
Now all you need is a function that conses a number to a list if it is even, and just produces the list otherwise.
Like this one:
fun cons_if_even (x, xs) = if x mod 2 = 0 then x::xs else xs
And then you have
fun evens xs = foldr cons_if_even [] xs
or inlined,
fun evens xs = foldr (fn (y, ys) => if y mod 2 = 0 then y::ys else ys) [] xs
It's more "natural" to use the standard filtering function, though:
fun evens xs = filter (fn x => x mod 2 = 0) xs

Understanding user defined append list Standard ml

Im having trouble understanding this implementation of lists in Standard ML. Here is how it is defined:
An append list is a (simple) implementation of the list abstract data type that makes construction cheap (O(1)), but makes destruction expensive (O(n)). The 'a alistNN and 'a alist types are defined as follows:
datatype 'a alistNN = Sing of 'a | Append of 'a alistNN * 'a alistNN
datatype 'a alist = Nil | NonNil of 'a alistNN
The 'a alistNN type represents the “non-nil” append lists, while the 'a alist type represents arbitrary (nil or
non-nil) append lists.
Im confused on how I would work with these lists/make these lists. For example I have to write a function that is defined as:
'a alist -> 'a alist -> 'a alist that appends to append lists.
Any help will be appreciated in understanding this list definition.
This data structure represents a list with a tree, where each internal node represents concatenation of its children, and each leaf is an element. For example, here's two possible representations for the list [1,2,3,4]:
val L1 = Append (Append (Sing 1, Sing 2), Append (Sing 3, Sing 4))
*
/ \
* *
/ \ / \
1 2 3 4
val L2 = Append (Append (Sing 1, Append (Sing 2, Sing 3)), Sing 4)
*
/ \
* 4
/ \
1 *
/ \
2 3
Appending these data structures is extremely easy; you just link them together with a new Append node. We could append the two examples above:
Append (L1, L2)
*
/ \
/ \
* *
/ \ / \
* * * 4
/ \ / \ / \
1 2 3 4 1 *
/ \
2 3
Obviously you'll also have to wrap these in NonNil as appropriate, but I'll leave that to you.
With normal lists,
datatype 'a normal_list = Nil | Cons of 'a * 'a normal_list
your Cons operator to prepend a single element is O(1), but to append two lists is O(n):
fun append (Nil, ys) = ys
| append (xs, Nil) = xs
| append (Cons (x, xs), ys) = Cons (x, append (xs, ys))
With these append lists,
datatype 'a alistNN = Sing of 'a | Append of 'a alistNN * 'a alistNN
datatype 'a alist = Nil | NonNil of 'a alistNN
your Append operator is now the O(1), but cons becomes the more difficult O(n) because, as you say, it requires destroying the list to rebuild it, since the head of the data structure is no longer the first element, but rather the point at which the list was most recently appended.
Im confused on how I would work with these lists/make these lists. For example I have to write a function that is defined as:
'a alist -> 'a alist -> 'a alist
that appends to append lists.
(Edit: Clarified this section.) You already have a constructor Append : 'a alistNN * 'a alistNN -> 'a alistNN that does just that. To make one that instead works for 'a alist, you have to pattern match against the different cases of 'a alist; only when both lists are NonNil can you use Append (since an empty list is not expressible as an 'a alistNN. The cases where either operand is Nil can be handled separately;
fun append Nil ys = ys
| append xs Nil = xs
| append (NonNil xs) (NonNil ys) = NonNil (Append (xs, ys))
One thing that becomes more difficult is if you want to prepend a single element in front of an 'a alist, i.e. a function with the signature 'a * 'a alist -> 'a alist:
fun cons (x, Nil) = NonNil (...)
| cons (x, NonNil (Sing y)) = NonNil (...)
| cons (x, NonNil (Append (ys, zs))) = NonNil (...)
In every case x is prepended. There are three cases when it comes to the list to which you're prepending x: Either the list is empty, the list is non-empty and contains a single element, or the list is non-empty and contains the Append of two other lists. In every case, the result is something NonNil, since prepending an x to a list will never give Nil.
The first two cases should be straight forward. The third case you have to think about where to put x in terms of the sub-lists ys and zs.
Like this you can build all the auxiliary functions found by typing open List; in a REPL. Even hd and tl are not completely trivial because they're bent on finding the split between the first element and the rest of the list. A useful function for testing purposes would be toList with the signature 'a alist -> 'a list. A funny one to make for these append lists is rev. :-)
Since you're probably not going to make foldl:
fun foldl f e Nil = e
| foldl f e (NonNil (Sing x)) = f (x, e)
| foldl f e (NonNil (Append (xs, ys))) =
foldl f (foldl f e (NonNil xs)) (NonNil ys)
For amusement, you could implement hd using foldl and throwing an exception:
fun hd xs =
let exception FoundIt of 'a
in foldl (fn (x, _) => raise FoundIt x) (fn _ => raise Empty) xs ()
handle FoundIt x => x
end
Here's a slightly related StackOverflow post: Standard ML functor examples

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 99 Problems #7: Prepend vs Append to List

This passes:
data Nested List a = Elem a | List [NestedList a]
flatten :: NestedList a -> [a]
flatten (Elem a) = [a]
flatten (List (x:xs)) = flatten x ++ flatten (List xs)
flatten (List []) = []
This fails:
data NestedList a = Elem a | List [NestedList a]
flatten :: NestedList a -> [a]
flatten (Elem a) = [a]
flatten (List (x:xs)) = flatten x : flatten (List xs)
flatten (List []) = []
Error is:
Couldn't match expected type `a' with actual type `[a]'
`a' is a rigid type variable bound by
the type signature for flatten :: NestedList a -> [a]
at 007.hs:2:12
Relevant bindings include
xs :: [NestedList a] (bound at 007.hs:4:18)
x :: NestedList a (bound at 007.hs:4:16)
flatten :: NestedList a -> [a] (bound at 007.hs:3:1)
In the first argument of `(:)', namely `flatten x'
In the expression: flatten x : flatten (List xs)
The difference is ++ instead of :. I know the former appends, the latter prepends, but why doesn't : work in this case? I don't understand the error.
Actually ++ is the concatenation operator, which expects both the operators to be a list in this particular case. Since flatten returns a list, ++ concatenates them happily.
But, : just prepends only one item to a list. Since flatten x in flatten x : flatten (List xs) returns a list, : throws this error.

How to flatten a list non-recursively in sml/nj?

fun flat [] = []
| flat (l::ls) = l # flat ls;
This will flatten a list.
Is there a way to non recursively do the same operation? Perhaps with HOFs?
You could use high-order function List.foldr:
fun flat xs = List.foldr (fn (x, acc) => x # acc) [] xs
As #Andreas said, the function above can be shortened:
fun flat xs = List.foldr op# [] xs
Although you would like to implement flat as an exercise, List.concat in the standard library does exactly the same thing.