how can I define new data type in ML, let's assume newList, such that it can consist lists of element 'a (int, real, etc.), nested lists, for example:
if my type 'a is int, values may be: [1], [1,[4]], [1,[5],[[5]]], etc.
thanks in advance for any help
EDITED
sorry without 1 in the example, different lists of int, I deleted it
You cannot. All elements in a list must be of the same type. In your example, some of the elements are of int type, and some are int list.
You can create something like this tree, but the syntax is not so nice to use :-)
datatype 'a multiList = Empty
| List of 'a multiList list
| E of 'a;
val x = List [E 1, List [E 1, List [E 4]], List [E 1, List [E 5]]];
datatype 'a multiList = E of 'a
| List of 'a multiList list
Your examples would be:
List [E 1]
List [E 1, List [E 4]]
List [E 1, List [E 5], List [List [E 5]]]
Related
Lets say I have nested lsit: [1, [2, 3, 4], [5, [6]]] and I want to count how many elements it has. In this case it is six elements. I have written such code for doing this:
totalElems :: [a] -> Int
totalElems (x:xs) = case (x, xs) of
(_, []) -> 0
(y:ys, _) -> 1 + totalElems ys + totalElems xs
(_, _) -> 1 + totalElems xs
But I've got an error:
a.hs:4:42:
Couldn't match expected type ‘a’ with actual type ‘[a0]’
‘a’ is a rigid type variable bound by
the type signature for totalElems :: [a] -> Int at a.hs:1:15
Relevant bindings include
xs :: [a] (bound at a.hs:2:15)
x :: a (bound at a.hs:2:13)
totalElems :: [a] -> Int (bound at a.hs:2:1)
In the pattern: y : ys
In the pattern: (y : ys, _)
In a case alternative:
(y : ys, _) -> 1 + totalElems ys + totalElems xs
How I can do this in Haskell?
You can't make freeform lists-within-lists like that in Haskell. Dynamically typed langues will tolerate silliness like that, but strongly-typed Haskell won't.
1 is of type Int, and [2,3,4] is of a different type [Int]. Things in a list have to be of the same type.
However, you could do something like this:
data Nest a = Elem a | List [Nest a]
example ::Nest Int
example = List [Elem 1, List [Elem 2, Elem 3, Elem 4], List [Elem 5, List [Elem 6]]]
countNest :: Nest a -> Int
countNest (Elem x) = 1
countNest (List xs) = sum $ map countNest xs
Let's say I have nested lsit: [1, [2, 3, 4], [5, [6]]]
You can't have that list. It won't type-check. Try typing it by itself in GHCi; it'll just spit an error message at you. Since this input can't exist in the first place, trying to write a function to process it is a doomed endeavor.
Instead, you need to define a custom data type for this. See the other answers.
As others have said, the simplest way to do this is with a different data structure, like the tree NovaDenizen defined. However, just so you know, Haskell's type system enables various ways of creating "lists" in which the elements have different types : see https://wiki.haskell.org/Heterogenous_collections
the Nested List can exist in Scheme, but is it legal to use nested-list in SML? or we can only use simple list in SML?
and if legal,
1) how to check wether the two input list have the same list structure. algorithm the atoms in the list are not equal.
2) Whatever the deep of the input list, how to delete all the atoms in the nested-list that equals to the input value: a. should use the original list and not create a new list.
There's no problem in having nested lists in Standard ML. For an example:
val foo = [ [1, 2, 3], [4, 5], [6] ]
is an example of an int list list, i.e., a list of lists of integers.
As for your additional questions.
1
If by same structure you mean whether the sublists contain the same number of elements, i.e, you want
val bar = [ [34, 4, 6], [2, 78], [22] ]
val baz = [ [1], [4, 6, 2], [3, 6] ]
val cmp_foo_bar = structureEq (foo, bar) (* gives true, since the lengths of the sublists match up *)
val cmp_foo_baz = structureEq (foo, baz) (* gives false, since they don't *)
Then you can simply make a recursive function on the lists, that compares the length of each sublist in turn.
Note, if the lists are nested more than once, you'll need a function for each level. (i.e., one for 'a list lists, one for 'a list list lists, etc.
2
You cannot make a function that "however deep the input list" does something to the elements in the list. The type system will not let you do this. This is similar to how you cannot make the following list:
val illegal_list = [ [1, 2], [ [1, 4], [2, 3] ] ]
This is due to a list only being allowed to contain one type of elements, so if you have an 'a list list, each element in the list must be an 'a list. You cannot have 'as directly.
You'll have to settle on how nested the lists are, and make a function specific to that depth.
There is no problem with nesting lists in SML, e.g. [[1, 2], [3, 4]] works just fine.
However, I suspect you actually mean something more general, namely the ability to nest "lists" in heterogeneous ways: [[1, [3]], 2]. This is not legal as such in SML. However, this is because such a thing is not really a list, it is a tree.
You can define trees easily as well, but you need a more general type definition than the one for list:
datatype 'a tree = L of 'a | T of 'a tree list
Then T[T[L 1, T[L 3]], L 2] is a representation of the "list" above. A function for computing the depth (or height) of such a tree looks like
fun depth (L _) = 0
| depth (T ts) = 1 + max (List.map depth ts)
where max needs to be defined in the obvious manner.
I have a list of tuples and I want to create the a list of elements from a specific position in the tuple.
My tuple is {A, B} and I have several of these in a list and i want to create the list of all the B elements.
Cheers!
You can use lists:map.
1> A = [{1,2},{3,4},{5,6}].
[{1,2},{3,4},{5,6}]
2> B = lists:map(fun ({_, V}) -> V end, A).
[2,4,6]
The function passed to the map will select the element required from the tuple and the result will be a list of all the elements in that particular position in the given list of tuples. The above code assumes that all tuples have same number of elements.
Yet another way is to just use a simple list comprehension:
[B || {_, B} <- L].
> L = [{a1,b1}, {a2,b2}, {a3,b3}].
[{a1,b1},{a2,b2},{a3,b3}]
> lists:foldr(fun({_, B}, Acc) -> [B | Acc] end, [], L).
[b1,b2,b3]
This is a quick sample, not tested, but it should work.
split_tuples([{A | B} | T], Acc) ->
NewAcc = [B | Acc],
split_tuples(T, NewAcc);
split_tuples([], Acc) ->
lists:reverse(Acc).
erlang's element/2 function does just that: return the nth element from a tuple.
Put that in a map or fold function, with position as a parameter, and you're done.
edit: some untested code example:
get_them_all(ListOfTuples,Index) ->
lists:map(fun(Tuple) -> element(Index,Tuple) end,ListOfTuples).
Say for instance I want to make a list type that allows for flexible nesting like so:
[[['a'],'a'],'a']
Would it be possible to implement this in haskell? How would I go about writing it's type signature? Any help would be awesome!!!
This isn't a list so much as a tree. As such you can represent it with a tree data type. One example is the rose tree in containers, whose definition is approximately:
data Tree a = Node a [Tree a]
But maybe more suitable tree type in this case would be something like this (which is incidentally the free monad of []; the rose tree is the cofree comonad):
data Tree a = Leaf a | Node [Tree a]
Using this type you could represent your "list" like this, for example:
Node [Node [Node [Leaf 'a'], Leaf 'a'], Leaf 'a']
You need to define your own datatype with different value constructors.
From ghci:
Prelude> data Val a = Val a | List [Val a] deriving (Show)
Prelude> [List [List [Val 'a']], Val 'a']
[List [List [Val 'a']],Val 'a']
And its type:
Prelude> :t [List [List [Val 'a']], Val 'a']
[List [List [Val 'a']], Val 'a'] :: [Val Char]
Also, checkout how JSON is represented in Real World Haskell: http://book.realworldhaskell.org/read/writing-a-library-working-with-json-data.html
(search for data JValue to find the relevant data type)
I'm trying to write a function in sml which 'unpacks' a nest list of arbitrary depth. For example unpack [[[1,2]]] should yield [1,2]. I 'm trying something like :
fun unpack xs = if nestedp (xs) then unpack (hd xs) else xs;
with
fun nestedp [_] = true
| nestedp _ = false;
sml doesn't like unpack defined this way because it infers that the type of unpack as 'a list -> 'a . The return of the call to hd is passed back into unpack but it now doesn't 'see' a list but a single variable.
Is it possible to unpack a nested list this way at all ?
You cannot do this for the built in list type, as you wouldn't be able to get the types to match up.
For instance, one might think it'd be possible with a function of type 'a list list -> 'a list, and then applying it recursively until it reaches a base case of a non-nested list. You would, however, not be able to detect the base case in any way, leaving your types mismatched.
You could, however, do it if you created your own list type:
datatype 'a nestableList = Cons of 'a * 'a nestableList
| NCons of 'a nestableList * 'a nestableList
| Nil;
Here, Cons and Nil would work the same as :: and [], while NCons would allow for nested list building.
As an example:
(* The list [[1, 2], [[3], [4, 5, 6]]] *)
val nlist = NCons(
Cons(1, Cons(2, Nil)),
NCons(
NCons(
Cons(3, Nil),
Cons(4, Cons(5, Cons(6, Nil)))
),
Nil
)
);
You could then flatten this nested list type like this:
fun flatten nls =
let
fun flatten_ Nil = []
| flatten_ (NCons(head, tail)) = flatten head # flatten tail
| flatten_ ( Cons(head, tail)) = head :: flatten tail
in
flatten_ nls
end;
Which then could be used like this
val flattenedNlist = flatten nlist; (* Yields [1, 2, 3, 4, 5, 6] *)
Here I have it yield a regular list, but it could easily be changed to return a list of the same type instead.