creating my own Concat function (SML) - functional-programming

I need to create my own concat function and am confused how I get the output I need. Example:
myconcat(["a", "b", "c"]) returns "abc"
([]) returns ""
I have this:
fun myconcat ([],L2) = L2
| myconcat(x::xs, L2) = x::myconcat(xs,L2);
Which just returns a list of my two strings. How would I get them to output what i need?

You don't appear to have the correct type, to start with.
The example has type string list -> string, where your function seems to have type 'a list * 'a list -> 'a list.
To concatenate two strings, you would use ^, not ::.
The former has type string * string -> string, while the latter has type 'a * 'a list -> 'a list. As strings are not lists in SML, trying to concatenate them with :: will cause a
type error.
To actually do what you want, in the simplest way, try
fun myconcat L = foldr (op^) "" L

Related

Why is my F# vector add function using tail recursion not working?

I cannot get this to work in F#. I am trying to write a tail recursive form of vector add and pass the previously calculated values using a. It is giving error "error FS0001: Type mismatch. Expecting a
''a'
but given a
''b list -> 'c list -> 'a list'
The types ''a' and ''b list -> 'c list -> 'a list' cannot be unified."
let rec vecadd a v1 v2 =
match (v1, v2) with
| ([], []) -> a
| (h1::t1, h2::t2) -> vecadd a::h1+h2 t1 t2
First of all, you need to add parentheses around (a::h1+h2). Otherwise, the compiler thinks that you are calling vecadd with a as the argument
and then prepending that to a list. Your code gets parsed as (vecadd a)::h1+h2 instead.
Once you add the parentheses, there is one more issue. In your recursive call, the argument a::h1+h2 is not right - the operator :: prepends a value to the front of a list and so it takes a value and a list of values. In your case, you are trying to use it to append a value to the end of the list.
You can fix this by using h1+h2::a to add the new element to the front of the list and then reversing the list before returning it in the [], [] case:
let rec vecadd a v1 v2 =
match (v1, v2) with
| ([], []) -> List.rev a
| (h1::t1, h2::t2) -> vecadd (h1+h2::a) t1 t2

Map a list of options to list of strings

I have the following function in OCaml:
let get_all_parents lst =
List.map (fun (name,opt) -> opt) lst
That maps my big list with (name, opt) to just a list of opt. An option can contain of either None or Some value which in this case is a string. I want a list of strings with all my values.
I am a beginner learning OCaml.
I don't think filter and map used together is a good solution to this problem. This is because when you apply map to convert your string option to string, you will have the None case to deal with. Even if you know that you won't have any Nones because you filtered them away, the type checker doesn't, and can't help you. If you have non-exhaustive pattern match warnings enabled, you will get them, or you will have to supply some kind of dummy string for the None case. And, you will have to hope you don't introduce errors when refactoring later, or else write test cases or do more code review.
Instead, you need a function filter_map : ('a -> 'b option) -> 'a list -> 'b list. The idea is that this works like map, except filter_map f lst drops each element of lst for which f evaluates to None. If f evaluates to Some v, the result list will have v. You could then use filter_map like so:
filter_map (fun (_, opt) -> opt) lst
You could also write that as
filter_map snd lst
A more general example would be:
filter_map (fun (_, opt) ->
match opt with
| Some s -> Some (s ^ "\n")
| None -> None)
lst
filter_map can be implemented like this:
let filter_map f lst =
let rec loop acc = function
| [] -> List.rev acc
| v::lst' ->
match f v with
| None -> loop acc lst'
| Some v' -> loop (v'::acc) lst'
in
loop [] lst
EDIT For greater completeness, you could also do
let filter_map f lst =
List.fold_left (fun acc v ->
match f v with
| Some v' -> v'::acc
| None -> acc) [] lst
|> List.rev
It's a shame that this kind of function isn't in the standard library. It's present in both Batteries Included and Jane Street Core.
I'm going to expand on #Carsten's answer. He is pointing you the right direction.
It's not clear what question you're asking. For example, I'm not sure why you're telling us about your function get_all_parents. Possibly this function was your attempt to get the answer you want, and that it's not quite working for you. Or maybe you're happy with this function, but you want to do some further processing on its results?
Either way, List.map can't do the whole job because it always returns a list of the same length as its input. But you need a list that can be different lengths, depending on how many None values there are in the big list.
So you need a function that can extract only the parts of a list that you're interested in. As #Carsten says, the key function for this is List.filter.
Some combination of map and filter will definitely do what you want. Or you can just use fold, which has the power of both map and filter. Or you can write your own recursive function that does all the work.
Update
Maybe your problem is in extracting the string from a string option. The "nice" way to do this is to provide a default value to use when the option is None:
let get default xo =
match xo with
| None -> default
| Some x -> x
# get "none" (Some "abc");;
- : string = "abc"
# get "none" None;;
- : string = "none"
#
type opt = Some of string | None
List.fold_left (fun lres -> function
(name,Some value) -> value::lres
| (name,None) -> lres
) [] [("s1",None);("s2",Some "s2bis")]
result:
- : string list = ["s2bis"]

Writing a function that is sum of functions

I have the following excercise to do:
Code a function that will be a summation of a list of functions.
So I think that means that if a function get list of functions [f(x);g(x);h(x);...] it must return a function that is f(x)+g(x)+h(x)+...
I'm trying to do code that up for the general case and here's something I came up with:
let f_sum (h::t) = fold_left (fun a h -> (fun x -> (h x) + (a x))) h t;;
The problem is I'm using "+" operator and that means it works only when in list we have functions of type
'a -> int
So, can it be done more "generally", I mean can we write a function, that is a sum of ('a -> 'b) functions, given in a list?
yes, you can make plus function to be a parameter of your function, like
let f_sum plus fs =
let (+) = plus in
match fs with
| [] -> invalid_arg "f_sum: empty list"
| f :: fs -> fold_left ...
You can generalize even more, and ask a user to provide a zero value, so that you can return a function, returning zero if the list is empty. Also you can use records to group functions, or even first class modules (cf., Commutative_group.S in Core library).

SML - collecting words in a trie using continuations

I have a
datatype trie = Node of char * (trie ref) list | Empty
And I want to collect all the words in the trie, using these two mutually recursive functions:
words_in_trie: trie -> (char list list -> 'a) -> 'a
all_words: trie ref list -> (char list list -> 'a) -> 'a
and then calling them with
fun all_entries t = all_words t (fn l => map (fn w => String.implode w) l);
This has to be done with continuations. I've written it in non-continuation form, as follows:
fun wt Empty = [[]]
|wt (Node(c,rl)) = map (fn (l) => c::l) (aw rl)
and aw [] = []
|aw [h] = wt (!h)
|aw (h::t) = (wt (!h))#(aw t)
But I can't figure out how to convert them into continuation form!
This is what I have so far, but it doesn't work:
fun words_in_trie Empty cont = cont[]
|words_in_trie (Node(c,rl)) cont = (all_words rl (fn r=> cont(c::r)))
and all_words [h] cont = words_in_trie (!h) cont
|all_words (h::t) cont = (words_in_trie (!h) cont)#(all_words t cont)
I've been stuck on this for ages, I will appreciate any help.
Since the inputs to the continuation are the postfix of words, you know that after the next continuation is called, the result has to be closer to the list of words in the trie and still be the postfix of the words. You can use this to determine that what the continuation is supposed to do is prepend the next letter up the trie (given a char list list, it'll prepend a char to every char list in the list).
fun words_in_trie Empty cont = cont[]
If the trie you're passing is Empty, then you have one word in that trie, and that's an empty string. The result you want is [""]. Recall that the last continuation converts every char list in the list to a string, so in order to get that result, you need to pass it a list with an empty char list for it to convert.
|words_in_trie (Node(c,rl)) cont = (all_words rl (fn r=> cont(c::r)))
Recall: the type of the continuation is char list list -> 'a. c is a char, so it can't be prepended to r, which is of type char list list.
all_words returns a list of all words contained in the list of tries rl, to which you want to apply the continuation (which prepends all chars up the trie). You have to build up the continuation so that in addition to prepending all chars from the nodes up the trie, it also prepends the char c from the current node. What you're looking for is something like this:
fn x => cont (map (fn y => c::y) x)
The above prepends c to every char list in the list, then passes it on to the next continuation, which goes on to prepend the next char.
Your all_words function looks fine to me.

Query on type expressions in ML

All,
Here is the type expression which I need to convert to a ML expression:
int -> (int*int -> 'a list) -> 'a list
Now I know this is a currying style expression which takes 2 arguments:
1st argument = Type int
and 2nd argument = Function which takes the previous int value twice and return a list of any type
I am having a hard time figuring such a function that would take an int and return 'a list.
I am new to ML and hence this might be trivial to others, but obviously not me.
Any help is greatly appreciated.
You get an int and a function int*int -> 'a list. You're supposed to return an 'a list. So all you need to do is call the function you get with (x,x) (where x is the int you get) and return the result of that. So
fun foo x f = f (x,x)
Note that this is not the only possible function with type int -> (int*int -> 'a list) -> 'a list. For example the functions fun foo x f = f (x, 42) and fun foo x f = f (23, x) would also have that type.
Edit:
To make the type match exactly add a type annotation to restrict the return type of f:
fun foo x (f : int*int -> 'a list) = f (x,x)
Note however that there is no real reason to do that. This version behaves exactly as the one before, except that it only accepts functions that return a list.

Resources