Apply list elements to a function - list

Would someone please explain why the code below,
let list = ["A"; "B"; "C"]
let rec processList2 aList str =
match aList with
| h::t -> let z = str + ", " + h
printfn "%s" z
processList2 t z
| [] -> aList |> ignore
returns the following,
val list : string list = ["A"; "B"; "C"]
> processList2 list "X";;
X, A
X, A, B
X, A, B, C
val it : unit = ()
>
instead of this?
val list : string list = ["A"; "B"; "C"]
> processList2 list "X";;
X, A
X, A, X, B
X, A, X, B, X, C
val it : unit = ()
>
The function is recursive and passes 'z' to 'str' with each pass, so it seems like it should work...
I really appreciate the experts' help here. I am trying to learn F# and struggling with lists.
Also, how does one declare a 'list of strings?' I had an issue where a list expected to return a unit instead of a string.

If we follow along with each step it should help us understand why you get the result you get:
processList2 list "X";;
The first iteration takes h::t or "A"::["B"; "C"]. It then sets z to "X" + ", " + "A".
The next iteration takes "B"::["C"]. It then sets z to "X, A" + ", " + "B".
As you can see "X" does not get inserted in each iteration. Rather z gets appended to and set through each iteration building on the last. To append "X" at each iteration it would need to be something like:
let list = ["A"; "B"; "C"]
// Append "X, " to each item
let mapList item = "X, " + item
// reduce to single comma seperated list
let redList l r = l + ", " + r
// apply map and reduce functions to given list
let result = list |> List.map(mapList) |> List.reduce(redList)
printfn "%s" result
If you wanted you could even use String.Join to reduce the list however that requires a few more hoops to jump through:
let list = ["A"; "B"; "C"]
let mapList item = "X, " + item
let joinList (lst:list<string>) = System.String.Join(", ", lst)
let result = list |> List.map(mapList) |> joinList
printfn "%s" result
As for you last question: how does one declare a 'list of strings?, the answer depends on what you mean by declare. Are you trying to declare a variable of that type or a parameter that accepts it?
Declaring a variable as a certain type if generally done like this: let lst:string list = ["A"; "B"; "C"] where the type is given after the : during the declaration. If it is in a parameter than you have to be a little more explicit as you have to tell the compiler that you are setting the parameters type and not the return type:
// Set the lst parameter type to be a list<string> (same as string list)
let joinList (lst:list<string>) = System.String.Join(", ", lst)
// fails as we are telling the compiler to expect a return of string list yet we are only returning string
let joinList lst:list<string> = System.String.Join(", ", lst)
// Explicitly set both return and parameters
let joinList (lst:string list):string = System.String.Join(", ", lst)
Typically this wont be required as the type inference system in F# is very good and figuring out what type you want/need in these situations.

Related

How to create a new list of lists from a list of lists in Haskell?

I've a field made of list of lists like this:
let list1 = ["a", "abcdefgh", "abc"]
I want to get a new field 5x5 such that there could be more then 5 lines or columns, but no less. It must be produced from the previous one by addition spaces ' ' or keeping them as they are, if there are more then 5 symbols. For additional lines no spaces needed. For example:
list2 = ["a ", "abcdefgh", "abc ", " ", " "]
or:
let list1 = ["a", "abcdefgh", "c", "d", "e", "f"]
list2 = ["a ", "abcdefgh", "c ", "d ", "e ", "f"]
I thought about map, replicate, and length, but I'm a little bit confused.
If it's possible, don't use libs (or use Data.Map only). Thank you
You need to determine the length of the strings. You can do this for example with a lambda expression, so then the mapping looks like:
func :: [String] -> [String]
func mylines = map (\x -> … ) linesOfFiles ++ replicate (5-length mylines) (replicate 5' ')
where x is thus string that will be mapped, and … is an expression to what that value is mapped. I leave filling in … as an exercise.
Usually it is better not to work with length: length takes linear time, and for infinite lists, this will even get the program into an infinite loop.
You can work with recursion to perform padding, something like:
padding :: Int -> a -> [a] -> [a]
padding 0 _ xs = …
padding n x [] = …
padding n x (x:xs) = …

SMLNJ function that returns as a pair a string at the beginning of a list

So im really confused as i am new to sml and I am having trouble with syntax of how i want to create my function.
the instructions are as follows...
numberPrefix: char list → string * char list
Write a function named numberPrefix that returns (as a pair) a string representing the digit characters at the
beginning of the input list and the remaining characters after this prefix. You may use the Char.isDigit and
String.implode functions in your implementation.
For example,
numberPrefix [#"a", #"2", #"c", #" ", #"a"];
val it = ("", [#"a", #"2", #"c", #" ", #"a") : string * char list
numberPrefix [#"2", #"3", #" ", #"a"];
val it = ("23", [#" ", #"a"]) : string * char list
Here is my code so far...
fun numberPrefix(c:char list):string*char list =
case c of
[] => []
|(first::rest) => if isDigit first
then first::numberPrefix(rest)
else
;
I guess what i am trying to do is append first to a seperate list if it is indeed a digit, once i reach a member of the char list then i would like to return that list using String.implode, but I am banging my head on the idea of passing in a helper function or even just using the "let" expression. How can I essentially create a seperate list while also keeping track of where i am in the original list so that I can return the result in the proper format ?
First of all, the function should produce a pair, not a list.
The base case should be ("", []), not [], and you can't pass the recursive result around "untouched".
(You can pretty much tell this from the types alone. Pay attention to types; they want to help you.)
If you bind the result of recursing in a let, you can access its parts separately and rearrange them.
A directly recursive take might look like this:
fun numberPrefix [] = ("", [])
| numberPrefix (cs as (x::xs)) =
if Char.isDigit x
then let val (number, rest) = numberPrefix xs
in
((str x) ^ number, rest)
end
else ("", cs);
However, splitting a list in two based on a predicate – let's call it "splitOn", with the type ('a -> bool) -> 'a list -> 'a list * 'a list – is a reasonably useful operation, and if you had that function you would only need something like this:
fun numberPrefix xs = let val (nums, notnums) = splitOn Char.isDigit xs
in
(String.implode nums, notnums)
end;
(Splitting left as an exercise. I suspect that you have already implemented this splitting function, or its close relatives "takeWhile" and "dropWhile".)

Ocaml - apply a function to every string in a string list and returning a new string list

I'm a beginner at OCaml and I'm a bit confused on using match. For this problem, I'm learning to work with functions on string lists that return string lists. I'm trying to run a function that returns a bool on every element in a string list and get back as an output a string list of those bools. For example, say you have the following:
let foo str =
(String.length str) > 3;;
let list1 = ["please";"help";"me"]
and you want to apply foo on every element in list1 with the following as the desired output:
output = [ "true";"true";"false"]
what I've done is obviously not working since I am not returning a string list:
let rec bar (ls : string list) : string list=
match foo ls with
| [] -> ()
| x :: xs -> x :: bar xs
;;
Does anyone have any ideas how I could do that? Thanks!
In your match expression, both cases should be returning a list since that is the type you want as your result (not ()), and you want to destructure the list (not the result of applying foo to the list) eg.
let rec bar (ls : string list) : string list=
match ls with
| [] -> []
| x :: xs -> (if (foo x) then "true" else "false") :: bar xs

Trying to get first word from character list

I have a character list [#"h", #"i", #" ", #"h", #"i"] which I want to get the first word from this (the first character sequence before each space).
I've written a function which gives me this warning:
stdIn:13.1-13.42 Warning: type vars not generalized because of value
restriction are instantiated to dummy types (X1,X2,...)
Here is my code:
fun next [] = ([], [])
| next (hd::tl) = if(not(ord(hd) >= 97 andalso ord(hd) <= 122)) then ([], (hd::tl))
else
let
fun getword [] = [] | getword (hd::tl) = if(ord(hd) >= 97 andalso ord(hd) <= 122) then [hd]#getword tl else [];
in
next (getword (hd::tl))
end;
EDIT:
Expected input and output
next [#"h", #"i", #" ", #"h", #"i"] => ([#"h", #"i"], [#" ", #"h", #"i"])
Can anybody help me with this solution? Thanks!
This functionality already exists within the standard library:
val nexts = String.tokens Char.isSpace
val nexts_test = nexts "hi hi hi" = ["hi", "hi", "hi"]
But if you were to build such a function anyway, it seems that you return ([], []) sometimes and a single list at other times. Normally in a recursive function, you can build the result by doing e.g. c :: recursive_f cs, but this is assuming your function returns a single list. If, instead, it returns a tuple, you suddenly have to unpack this tuple using e.g. pattern matching in a let-expression:
let val (x, y) = recursive_f cs
in (c :: x, y + ...) end
Or you could use an extra argument inside a helper function (since the extra argument would change the type of the function) to store the word you're extracting, instead. A consequence of doing that is that you end up with the word in reverse and have to reverse it back when you're done recursing.
fun isLegal c = ord c >= 97 andalso ord c <= 122 (* Only lowercase ASCII letters *)
(* But why not use one of the following:
fun isLegal c = Char.isAlpha c
fun isLegal c = not (Char.isSpace c) *)
fun next input =
let fun extract (c::cs) word =
if isLegal c
then extract cs (c::word)
else (rev word, c::cs)
| extract [] word = (rev word, [])
in extract input [] end
val next_test_1 =
let val (w, r) = next (explode "hello world")
in (implode w, implode r) = ("hello", " world")
end
val next_test_2 = next [] = ([], [])

Ocaml introduction

i'm trying to learn ocaml right now and wanted to start with a little program, generating all bit-combinations:
["0","0","0"]
["0","0","1"]
["0","1","0"]
... and so on
My idea is the following code:
let rec bitstr length list =
if length = 0 then
list
else begin
bitstr (length-1)("0"::list);
bitstr (length-1)("1"::list);
end;;
But i get the following error:
Warning S: this expression should have type unit.
val bitstr : int -> string list -> string list = <fun>
# bitstr 3 [];;
- : string list = ["1"; "1"; "1"]
I did not understand what to change, can you help me?
Best regards
Philipp
begin foo; bar end executes foo and throws the result away, then it executes bar. Since this makes only sense if foo has side-effects and no meaningful return value ocaml emits a warning if foo has a return value other than unit, since everything else is likely to be a programmer error (i.e. the programmer does not actually intend for the result to be discarded) - as is the case here.
In this case it really does make no sense to calculate the list with "0" and then throw it away. Presumably you want to concatenate the two lists instead. You can do this using the # operator:
let rec bitstr length list =
if length = 0 then
[list]
else
bitstr (length-1)("0"::list) # bitstr (length-1)("1"::list);;
Note that I also made the length = 0 case return [list] instead of just list so the result is a list of lists instead of a flat list.
Although sepp2k's answer is spot on, I would like to add the following alternative (which doesn't match the signature you proposed, but actually does what you want) :
let rec bitstr = function
0 -> [[]]
| n -> let f e = List.map (fun x -> e :: x) and l = bitstr (n-1) in
(f "0" l)#(f "1" l);;
The first difference is that you do not need to pass an empty list to call the function bitsr 2 returns [["0"; "0"]; ["0"; "1"]; ["1"; "0"]; ["1"; "1"]]. Second, it returns a list of ordered binary values. But more importantly, in my opinion, it is closer to the spirit of ocaml.
I like to get other ideas!
So here it is...
let rec gen_x acc e1 e2 n = match n with
| 0 -> acc
| n -> (
let l = List.map (fun x -> e1 :: x) acc in
let r = List.map (fun x -> e2 :: x) acc in
gen_x (l # r) e1 e2 (n - 1)
);;
let rec gen_string = gen_x [[]] "0" "1"
let rec gen_int = gen_x [[]] 0 1
gen_string 2
gen_int 2
Result:
[["0"; "0"]; ["0"; "1"]; ["1"; "0"]; ["1"; "1"]]
[[0; 0]; [0; 1]; [1; 0]; [1; 1]]