f# System.Char.ToUpper - list

I have an exercise that asks for a function that converts all characters of a string to uppercase using
System.Char.ToUpper
So first I changed the string to a char array and changed the array into a list of chars
let x = s.ToCharArray()
List.ofArray x
Next, I thought I would use List.iter to iterate through my list and use the System.Char.ToUpper function on each character.
List.iter (fun z -> (System.Char.ToUpper(z)))
This is not working however. I get an error 'The expression was supposed to have unit but here has char.' What am I doing wrong? Is it a flaw in logic or syntax?

This needs some unpacking.
First, your core mistake: System.Char.ToUpper is a function. It takes a char and returns another char. It doesn't somehow "update" its argument to a new value.
let x = 'a'
let y = System.Char.ToUpper x // y = 'A', x = 'a'.
In the above code, I give name y to the result of the function. The value of y is 'A', but the value of x is still 'a'. After calling the function, x hasn't changed.
From this mistake, all the rest follows.
Second, List.iter is a function that, for every element of a list, makes something "happen". It doesn't replace each element of a list with something new, nor does it create a new list. It just makes something happen for every element. The simplest example of such "something" is printing out to console:
List.iter (fun x -> printfn "%i" x) [1; 2; 3] // Prints "1", then "2", then "3"
Notice that this function takes two arguments: the function that represents the something that need to happen, and the list from which to take the elements. In your question, you seem to be missing the second argument. How would List.iter know which list to use?
The first argument of List.iter needs to be a function that returns unit. This is a special type in F# that basically means "no value". When a function returns no value, it means that the only reason for calling it was to make something external happen (known in functional programming as "side-effect"). This is why List.iter requires the function to return unit - it's extra protection from accidentally supplying wrong function, just as you did, actually: the function you provided returns char. This is why you receive the error that you receive.
Third, just like with ToUpper, calling List.ofArray doesn't somehow "update" x to be a list. Instead, it returns a list. If you don't give that returned list a name, it will just be lost. Which means that the way you're calling List.ofArray is futile.
What you actually need is to (1) take the sequence of characters in your string, then (2) convert it to a new sequence where each character is upper case, then (3) glue those characters back together to get a new string.
Step (1) is a no-op, because .NET strings are already sequences of chars (i.e. they implement IEnumerable<char>). Step (2) is accomplished via a common operation called Seq.map. It's an operation that converts a sequence to a new sequence by applying given function to every element. The "given function" in this case will be System.Char.ToUpper. Step (3) can be accomplished via String.concat, but you'd need to convert each char to a string first, because String.concat takes a sequence of strings, not chars.
let chars = s
let upperChars = Seq.map System.Char.ToUpper chars
let strChars = Seq.map string upperChars
let result = String.concat "" strChars
Or this can be done in a shorter way, without giving each step's result a separate name, but by piping each result straight into the next operation:
let result =
s
|> Seq.map System.Char.ToUpper
|> Seq.map string
|> String.concat ""
And finally, there is actually a much shorter way to do it, but it's so ridiculously obvious, it feels like cheating.
The thing is, because strings are sequences, it kinda makes sense for them to have all the sequence operations. And guess what? They do! Specifically, there is a function String.map, which does the same thing as Seq.map, but for strings:
let result = String.map System.Char.ToUpper s

Related

Clarification needed in second parameter to List.init (F#)

Could you explain the second parameter in List.init
let test2 = List.init 100000 (fun _ -> System.Random().Next(-50, 51));;
From the declaration of List.init available here; what I understand is that init takes an int and "a function that takes an index and returns a generic value" as parameters. The return value is a list of the generic type passed.
But I don't understand how is the function being applied in the given let binding.
Thanks.
List.init takes an integer for the size of the list and then a function that will be used to fill each element. This function takes in the current index of the element being filled (ie. an int). The Type of the elements in your list then depends on the return type of the 2nd function. In your case an int.
In the example in the question the function fun _ -> System.Random().Next(-50, 51) will just pick random value to fill the list with. Since it is new-ing up Random every time you will get the same value every time because computers and randomness are not very well acquainted. the _ is used in many languages to indicate that we don't care about the value of the parameter because we are not going to use it. So here _ is used as an anonymous generic parameter.
For an actual "random" value you could move the Random() call outside the function and close over it or you could technically use the item index as a seed number. I am not recommending this but it does illustrate what that function takes.
let test1 = List.init 100000 (fun i -> System.Random(i).Next(-50, 51))
As I mentioned something like this is more likely what you are after:
//Random
let random = System.Random()
// int -> int
let generate (_:int) = random.Next(-50, 51)//note this has the signature we need for the 2nd parameter of List.init
// generate the list
let test2 = List.init 10 generate;;
The _ can also be used in matching. Here we have a tuple we want to deconstruct to get to it's values.
let person = ("Bob","Builder")
let (firstname,lastname) = person
let (_,surname) = person
If we don't care about the firstname we don't have to get it but can still use the same syntax, we just use _ to indicate we do not care about the value.
Reference Symbol and Operator reference
I think I understand now. fun _ -> System.Random().Next(-50, 51) is an anonymous function that uses _ as a wildcard placeholder for parameter and returns a random number.
So, it can be used as second parameter to init, and get a list of randomly generated integers back.

Function that converts a sequence to a list in OCaml

I want to convert a sequence to a list using List.init. I want at each step to retrieve the i th value of s.
let to_list s =
let n = length s in
List.init n
(fun _i ->
match s () with
| Nil -> assert false
| Cons (a, sr) -> a)
This is giving me a list initialized with the first element of s only. Is it possible in OCaml to initialize the list with all the values of s?
It may help to study the definition of List.init.
There are two variations depending on the size of the list: a tail recursive one, init_tailrec_aux, whose result is in reverse order, and a basic one, init_aux. They have identical results, so we need only look at init_aux:
let rec init_aux i n f =
if i >= n then []
else
let r = f i in
r :: init_aux (i+1) n f
This function recursively increments a counter i until it reaches a limit n. For each value of the counter that is strictly less than the limit, it adds the value given by f i to the head of the list being produced.
The question now is, what does your anonymous function do when called with different values of i?:
let f_anon =
(fun _i -> match s () with
|Nil -> assert false
|Cons(a, sr) -> a)
Regardless of _i, it always gives the head of the list produced by s (), and if s () always returns the same list, then f_anon 0 = f_anon 1 = f_anon 2 = f_anon 3 = hd (s ()).
Jeffrey Scofield's answer describes a technique for giving a different value at each _i, and I agree with his suggestion that List.init is not the best solution for this problem.
The essence of the problem is that you're not saving sr, which would let you retrieve the next element of the sequence.
However, the slightly larger problem is that List.init passes only an int as an argument to the initialization function. So even if you did keep track of sr, there's no way it can be passed to your initialization function.
You can do what you want using the impure parts of OCaml. E.g., you could save sr in a global reference variable at each step and retrieve it in the next call to the initialization function. However, this is really quite a cumbersome way to produce your list.
I would suggest not using List.init. You can write a straightforward recursive function to do what you want. (If you care about tail recursion, you can write a slightly less straightforward function.)
using a recursive function will increase the complexity so i think that initializing directly the list (or array) at the corresponding length will be better but i don't really know how to get a different value at each _i like Jeffrey Scofield said i am not really familiar with ocaml especially sequences so i have some difficulties doing that:(

Check if a word is in a list OCAML using fold

Suppose I want to extract a 4-letter word out of 6-letter word, say "hank" out of "thanks". Suppose there is also a list of 4-letter words that makes sense and I want to check that whether the 4-letter word I just extracted makes sense (i.e if it shows up in the list of 4-letter words) and then I want to return a list of all 6-letter words from which extracted meaningful 4-letter words come.
My thought is:
let is_4_init lst =
let acc = ([]) in
let f (group) x =
let y = String.sub x 1 4 in
if List.mem y my_4words_list then ([x]) in
let (final_group) = List.fold_left f acc lst in final_group
Error: This variant expression is expected to have type unit
The constructor :: does not belong to type unit
why is this the case?
Thank you!
If you use if ... then without an else, then the type of the result must be unit. That's because the type needs to be the same for both cases. unit is the type of the value (), and is used when the result of an expression isn't particularly interesting.
Your function f should be returning an accumulated result, so it does return an interesting result. Returning unit is not what you want. You need to figure out what f should return when the test is false.
As a side comment, it's somewhat notable that you're not using the parameter named group anywhere.

Replacing element in a list of lists in Haskell

I have a list of lists like so:
[["BBBBBBBB",
"BWFFFPFGB",
"BWFFFPFGB",
"BWFFMPFGB",
"BWFFFPF_B",
"BWFFFPF6B",
"BBBBBBB"]]
I've done a little research and have found out how to access individual elements using the !! operator. But when it comes to searching for a certain element 'M' I'm not sure how to go about that. My friend said I need to use something like (x:xs):xss on a list, but when I try this in the WinGHCi haskell program I get this.
Prelude> let list = [["BBBBBBBB",
"BWFFFPFGB",
"BWFFFPFGB",
"BWFFMPFGB",
"BWFFFPF_B",
"BWFFFPF6B",
"BBBBBBB"]]
Prelude> head(x:xs):xss
<interactive>:192:2: Not in scope: `x'
<interactive>:192:4: Not in scope: `xs'
<interactive>:192:8: Not in scope: `xss'
I understand that I declare the name as list and not x:xs but even when I declare it as x:xs I still get the errors. I'm probably still a little new to haskell to really understand what to do so I may be going about this way wrong.
I've looked here Replace individual list elements in Haskell? because eventually I want to replace the M with something different but I'm not completely sure how I would implement that.
Any help/guidance is appreciated, thanks!
First let's see how to replace a W with M
charWM :: Char -> Char
charWM 'W' = 'M' -- If you see W, put M.
charWM x = x -- If you see anything else, put it back as is.
You can rewrite that function how you like by adding other letter transformations.
Now let's make that work over a list. There's a great function map :: (a ->b) -> [a] -> [b] that lets you apply a function on every element on a list.
stringWM :: String -> String
stringWM xs = map charWM xs -- do charWM to everything in xs.
For example stringWM "QWERTY WILL WIN" = "QMERTY MILL MIN"
Next we can do that to a list of lists:
lolWM :: [String] -> [String]
lolWM xss = map stringWM xss
(String is a type synonym for [Char].)
Let's test that out in ghci:
*Main> list'
["BBBBBBBB","BWFFFPFGB","BWFFFPFGB","BWFFMPFGB","BWFFFPF_B","BWFFFPF6B","BBBBBBB"]
*Main> lolWM list'
["BBBBBBBB","BMFFFPFGB","BMFFFPFGB","BMFFMPFGB","BMFFFPF_B","BMFFFPF6B","BBBBBBB"]
All good.
Your example wasn't exactly list', it was [list'] which has 1 element, so to work on that we'd need to map lolWM. Often we wouldn't bother writing stringWM or lolWM and go directly to lists of lists of lists, if that's what we needed:
lololWM = (map.map.map) charWM
map.map.map means map the map of the map. You can allow that to blow your mind a little, or you can just say list of list of list of Char, so map map map - one map per list level.
In the future, maybe you'll want to replace W with Strings instead of characters.
rewriteChar :: Char -> String
rewriteChar 'W' = "--^--"
rewriteChar x = [x] -- put x in a list to make it a string
This time, map isn't enough: map rewriteChar "QWERTY WILL WIN" gives
["Q","--^--","E","R","T","Y"," ","--^--","I","L","L"," ","--^--","I","N"]
We could use concat on that to flatten it into a single list, but it's more fun to do
rewriteString = concatMap rewriteChar
So now rewriteString "QWERTY WILL WIN" give us "Q--^--ERTY --^--ILL --^--IN".
For more mindblowing things to try, there's "QWERTY WILL WIN" >>= rewriteChar and "Hello Mum" >>= \x -> [x,x,x]
First of all, virtually all "variables" in Haskell are immutable, so there's no "changing a list", there are modified copies.
Second, you need to find an element by some criteria. To do that, you need to traverse a list. - This can be done using recursion. Filtering can be done using a function passed as an argument of your traversing function (this function must take an element and return a boolean value).
Try to put the above together and make your own function. Start with a type signature, it shows what you want to do: to take a list of Char (it's better to generalize to a generic type) and a function which possibly changes an element and return a modified list:
replaceFunc :: (Char -> Char) -> String -> String
Also, read http://www.haskell.org/haskellwiki/How_to_work_on_lists , there's a hint there how to apply some function to specific elements only.

Substring in Haskell

I'm supposed to split a string and return the substring that occurs before a passed character, but we're just starting Haskell, and it is like Chinese to me. I've been messing with it, but no luck.
Here's what I have so far:
--spanString returns substring of string s before char c
spanString (c, [s])::(c, [s]) -> []
spanString (c, a:b) =
let (x, y) = spanString (c, b)
in
if a < c then (a:x,y)
else (x, a:y)
What am I messing up?
First of all, your type signature is completely messed up. It must either be absent or be of the form spanString :: <some type>. Even if we ignore the (c, [s]) standing before the double colon, the rest is still something strange. One can read it as "a function taking values of type (c, [s]) to values of type [] for any c and s" (c and s are type variables). First, there is no type [] in Haskell. There is not going be a list type without its element type. Next, we can't work with any c and s. We must be able to compare them, right?
Actually, let's avoid using polymorphism for now and specify exactly which types we want. We want a character and a list of characters, packed up into a tuple for some reason: (Char, [Char]). Note that Char starts with a capital letter, which means it's not a type variable, but rather a concrete type. What about our result type? If you trust the problem description, you need to return a list of characters ([Char]), but if you look at the code, it obviously returns tuples of lists (([Char], [Char])). Okay, maybe the second list is useful, let's leave it for now:
spanString :: (Char, [Char]) -> ([Char], [Char])`
Now your code compiles.
However, when run, it crashes with exception: Non-exhaustive patterns in function spanString. This is because you don't handle the case when the passed list is empty. If you do that, by adding an equation like
spanString (_, []) = ([], [])
, your function runs well, but now let's look at what it does. It turns out you have a function for list partitioning: it returns all characters of the given string less than c as the first element of the tuple and all other characters as the second element. Seems like a bug to me (you've implemented a completely different function!).
Err, quite a lot.
First, your type declaration is wrong. Haskell uses upper case names for types, and it doesn't pass parameters in brackets like most languages do. We write
y = sin x
instead of
y = sin (x)
You probably want something like
spanString :: Char -> String -> String
Your definition of spanString is syntactically right, but still wrong. Think about it this way: if first character doesn't match then you want to spanString the rest of the string and then return the result with the first character prepended. If the first character does match then you want to return "".
Your type definition is wrong .
spanString :: Char-> String-> String
spanString _ [] = []
spanString c (x:xs) | c==x = []
| otherwise = x:spanString c xs
Just for information, utility functions like this can almost always be found in Prelude, or one of the standard libraries. In this case, takeWhile will help:
spanString :: (Char, String) -> String
spanString (c, s) = takeWhile (/= c) s
(i.e., keep taking characters while they don't equal c).
Passing arguments in a tuple is slightly odd, but if that's what's required then so be it.