print/return cons version of a list in SML - sml

I want smlnj to return a list in its cons form when I input a list in the regular list notation. Is there a way to get smlnj to do this for me?
Here is an example:
input: [1,2,3]
output: 1::2::3::[]
I want to use this to understand how more complicated int list lists are stored internally through some examples.

You can get pretty close by creating your own list type. Here we write empty instead of [], and ::: instead of ::, but otherwise it's identical to normal lists.
datatype 'a mylist = empty | ::: of 'a * 'a mylist
infixr 5 :::
fun mylist (xs: 'a list) =
case xs of
[] => empty
| x :: xs' => x ::: mylist xs'
SML/NJ will show values of this type without any syntax sugar.
- mylist [1,2,3];
val it = 1 ::: 2 ::: 3 ::: empty : int mylist

You could extrapolate out the function to convert elements to strings and get a a function to convert a 'a list into a string.
fun listToString(_, []) = "[]"
| listToString(f, x::xs) =
f x ^ " :: " ^ listToString(f, xs);
Then:
listToString(Int.toString, [1,2,3]);
(* "1 :: 2 :: 3 :: []" *)
listToString(
fn x => "(" ^ listToString(Int.toString, x) ^ ")",
[[1, 2], [3, 4]]
);
(* "(1 :: 2 :: []) :: (3 :: 4 :: []) :: []" *)

Related

Int lists in functions

Does this function take two int lists "x and y" and return an int list of y-x?
let rec fun4 (l: int list) :int list =
begin match l with | [] -> []
| [_] -> []
| x::y::rest -> (y-x)::(fun4 (y::rest))
end
A list is defined as a recursive type:
type 'a list =
| [] of 'a list (* the empty case *)
| ( :: ) of 'a * 'a list
So you basically have two constructors: [] which is the empty list, and x :: other_list which is a list with x as head and other_list as tail. The use of these constructors makes it easy to define a list: [0; 1; 2; 3] is exactly the same of 0 :: 1 :: 2 :: 3 and of (::) (0, (::) (1, (::) (2, (::) (3, [])))) (which is not very pleasant to read).
Recursive algebraic types, here we have the conjunction of sums ([] and (::)) and products (('a * 'a list)), combined with pattern matching make it possible to describe all sorts of common data structures, as well as their functions for consuming, modifying etc.
In your example, you use pattern matching to deconstruct the list:
let rec fun4 my_list =
match my_list with
(* if my list is empty, I can't process the function so
I return the empty list *)
| [] -> []
(* if my list my list has only one element, I can't process the function
so, like in the previouse case, I return the empty list *)
| [ _ ] -> []
(* Here is the last case of the function, If I almost have two elements in the
list. Remember that empty list is also a list ! *)
| x :: y :: rest -> (y - x) :: (fun4 (y :: rest))
As you can see, Recursives Algebraic data types coupled with pattern matching are a powerful for describing data structures (like list but also many others) and for writing function that use those data structures.

Haskell How to rewrite a code using fold-function?

I want to rewrite (or upgrade! :) ) my two functions, hist and sort, using fold-functions. But since I am only in the beginning of my Haskell-way, I can't figure out how to do it.
First of all, I have defined Insertion, Table and imported Data.Char:
type Insertion = (Char, Int)
type Table = [Insertion]
import Data.Char
Then I have implemented the following code for hist:
hist :: String -> Table
hist[] = []
hist(x:xs) = sortBy x (hist xs) where
sortBy x [] = [(x,1)]
sortBy x ((y,z):yzs)
| x == y = (y,z+1) : yzs
| otherwise = (y,z) : sortBy x yzs
And this one for sort:
sort :: Ord a => [a] -> [a]
sort [] = []
sort (x:xs) = paste x (sort xs)
paste :: Ord a => a -> [a] -> [a]
paste y [] = [y]
paste y (x:xs)
| x < y = x : paste y xs
| otherwise = y : x : xs
What can I do next? How can I use the fold-functions to implement them?
foldr f z on a list replaces the "cons" of the list (:) with f and the empty list [] with z.
This thus means that for a list like [1,4,2,5], we thus obtain f 1 (f 4 (f 2 (f 5 z))), since [1,4,2,5] is short for 1 : 4 : 2 : 5 : [] or more canonical (:) 1 ((:) 4 ((:) 2 ((:) 5 []))).
The sort function for example can be replaced with a fold function:
sort :: Ord a => [a] -> [a]
sort = foldr paste []
since sort [1,4,2,5] is equivalent to paste 1 (paste 4 (paste 2 (paste 5 []))). Here f thus takes as first parameter an element, and as second parameter the result of calling foldr f z on the rest of the list,
I leave hist as an exercise.

SML only accepting int list when it should be a real list

I am trying to write a simple add function that takes two real lists and adds the matching indices together and generates a real list, but for some reason I can't get it to accept real lists as the parameters, but instead only int lists.
fun add (nil, _) = nil
| add (_, nil) = nil
| add (a :: b, x :: y) = (a + x) :: add (b,y)
When I try running my test input, val addTest = add([1.0, 2.0, 3.0], [0.1, 0.2, 0.3]); it gives me:
Error: operator and operand do not agree [tycon mismatch]
operator domain: int list * int list
operand: real list * real list
And I am just curious as to why SML is defaulting to an int list even though the "+" operand is used for both reals and ints. Shouldn't it be accepting `a list instead of just int lists?
Yes, + (along with other arithmetic operators) is overloaded but not parametrically polymorphic.
So you can do 1.0 + 1.0 and 1 + 1 and they give a real and an int respectively.
But fun f x y = x + y can infer to either, so the compiler defaults to the int overload.
As an addition to your own answer, you can do with a single : real in your code:
fun add ([], _) = []
| add (_, []) = []
| add (x::xs, y::ys) = (x + y : real) :: add (xs, ys)
and it will infer that you must mean real in all the other places, too.
You could generalise this operation into one called zipWith:
- fun zipWith f [] _ = []
| zipWith f _ [] = []
| zipWith f (x::xs) (y::ys) = f (x, y) :: zipWith f xs ys
> val ('a, 'b, 'c) zipWith = fn :
('a * 'b -> 'c) -> 'a list -> 'b list -> 'c list
- val add = zipWith (op + : real * real -> real)
> val add = fn : real list -> real list -> real list
- add [1.0, 2.0, 3.0] [4.0, 5.0, 6.0];
> val it = [5.0, 7.0, 9.0] : real list
I found out that the default behavior for SML in a case like this is to default to int behavior, so if you have an operand that works for either reals or ints it will be evaluated as an int. As for the method above I was able to get my desired behavior by specifying the parameters in the tuple to be real lists like so:
fun add (nil, _) = nil
| add (_, nil) = nil
| add (a::b : real list, x::y : real list) = (a + x) :: add (b,y)

Combining two functions in OCaml

My task is to remove the duplicates from a list. To do that I have to first sort the list.
I have written the function that sorts the list and the one that remove the
duplicates(once they are sorted) but I don't know how to combine them.
Example:
input: [4;5;2;2;1;3;3]
output: [1;2;3;4;5]
let rec setify = function
| [] -> []
| x :: l -> insert x (setify l)
and insert elem = function
| [] -> [elem]
| x :: l -> if elem < x then elem :: x :: l
else x :: insert elem l;;
let rec rem =function
|[] -> []
| x :: []-> x :: []
| x :: y :: rest -> if x = y then rem (y :: rest)
else x :: rem (y :: rest) ;;
You want to make the function that takes a list, creates the sorted list, and deduplicates that. In other words, you want:
let task list =
let sorted_list = setify list in
rem sorted_list
It is possible to do this in arbitrarily more complicated ways, but the above is one straightforward, one-action-per-line version. Since the phrasing of the title of your question invites it, here is one of the more sophisticated ways:
(* it's possible to write a generic combinator of functions, that takes two functions f and g *)
let combine f g =
(* and returns a function *)
fun x ->
(* that maps x to f(g(x)) *)
f (g x)
(* this function is typed as:
val combine : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b = <fun>
*)
(* the task can then be expressed as the combination of setify and rem: *)
let task = combine rem setify
Don't use this style unless something is actually gained from it. Most of
the times it only makes programs less readable and slower with no corresponding benefit. *)

Haskell iterate over a list

I know you suppose to think differently in Haskell, but can someone give me a quick answer on how to iterate over a list or nested list and print out a character based on the value of the list element.
list1 = [[1 0 0][0 1 0][0 0 1]]
By iterate through this nested list, it should print out x for 0 and y for 1
yxx
xyx
xxy
Thanks
First of all, I think you mean:
list1 :: [[Int]]
list1 = [[1,0,0],[0,1,0],[0,0,1]]
As for what you want:
valueOf :: Int -> Char
valueOf 0 = 'x'
valueOf 1 = 'y'
valueOf _ = 'z'
listValues :: [[Int]] -> [String]
listValues = map (map valueOf)
printValues :: [[Int]] -> IO ()
printValues = putStrLn . unlines . listValues
And then in ghci:
*Main> printValues list1
yxx
xyx
xxy
Try this:
fun :: [[Int]] -> [String]
fun = (map . map) (\x -> if x == 0 then 'x' else 'y')
If you really need printing of result:
printSomeFancyList :: [[Int]] -> IO ()
printSomeFancyList = putStrLn . unlines . fun
define f by something like
f x = if x == 0 then 'x' else 'y'
then
map (map f) [[1,0,0],[0,1,0],[0,0,1]]
is what you want or if you want it fancier:
map' = map.map
map' f [[1,0,0],[0,1,0],[0,0,1]]
The solutions using map are the preferred Haskell style. But while you're learning, you may find explicit recursion easier to follow. Like so:
charSub :: Int -> Char
charSub 0 = 'x'
charSub 1 = 'y'
charSub x = error "Non-binary value!"
listSub :: [Int] -> String
listSub [] = []
listSub (x:xs) = (charSub x) : (listSub xs)
nestedSub :: [[Int]] -> String
nestedSub [] = []
nestedSub (y:ys) = (listSub y) ++ "\n" ++ (nestedSub ys)
map does pretty much the same thing--it applies a function to each element in a list. But it may be easier to see what's going on here.
If you are interested in arbitrary nested lists, then you can write something like this (an arbitrary nested list is essentially a tree):
data Nested a = Leaf a | Nest [Nested a] deriving Show
traverse :: Nested Integer -> Nested Char
traverse (Leaf x) = Leaf (valueOf x)
traverse (Nest xs) = Nest (map traverse xs)
valueOf :: Integer -> Char
valueOf 0 = 'x'
valueOf 1 = 'y'
valueOf _ = 'z'
With that you can do:
Main> let nl = Nest [Leaf 1, Leaf 0, Nest [Leaf 0, Leaf 0, Leaf 1, Nest [Leaf 1, Leaf 1, Leaf 0]], Nest [Leaf 1, Leaf 1]]
Main> traverse nl
Nest [Leaf 'y',Leaf 'x',Nest [Leaf 'x',Leaf 'x',Leaf 'y',Nest [Leaf 'y',Leaf 'y',Leaf 'x']],Nest [Leaf 'y',Leaf 'y']]
The function traverse takes an arbitrary nested list of Integers and returns a corresponding nested list of Chars according to the valueOf rule
iterateList = foldl1 (>>).concat.intersperse [putStrLn ""].(map.map) (\c -> putStr $ if (c==0) then "X" else "Y")
The solutions
cambiar = putStr.unlines.(map (map f)) where f x = if x == 0 then 'x' else 'y'