what is the difference between [string()] and list() in erlang? - erlang

Erlang: what is the difference between [string()] and list() ??
I saw them as return types of ct_telnet:cmd and ct_ssh:exec ?
http://erlang.org/doc/man/ct_ssh.html
exec(SSH, Command, Timeout) -> {ok, Data} | {error, Reason}
Types:
Data = list()
http://erlang.org/doc/man/ct_telnet.html
cmd(Connection, Cmd, Opts) -> {ok, Data} | {error, Reason}
Types:
Data = [string()]

The type list() stands for any list, without specifying the type of its elements. Another way to write it is [_] or [term()].
A string() is a special case of list(): it is a list containing integers representing Unicode code points (or Latin-1 characters, if less than 256, or ASCII characters, if less than 128). Another way to write string() is list(char()) or [char()].
A [string()] is a list of strings. This type can also be written as list(string()). Since it is a special case of a list, it is also valid (though less informative) to write it as list().

Formally there is no such type as "string" in Erlang, however strings are denoted using a list of codes. So essentially
String() -> [Positive_Integer()] (list of positive integers)
[String()] -> [[Positive_Integer()]] (list of list of positive integers)
where [] denotes a list.

Related

How to split F# result type list into lists of inner type

I have a list/sequence as follows Result<DataEntry, exn> []. This list is populated by calling multiple API endpoints in parallel based on some user inputs.
I don't care if some of the calls fail as long as at least 1 succeeds. I then need to perform multiple operations on the success list.
My question is how to partition the Result list into exn [] and DataEntry [] lists. I tried the following:
// allData is Result<DataEntry, exn> []
let filterOutErrors (input: Result<DataEntry, exn>) =
match input with
| Ok v -> true
| _ -> false
let values, err = allData |> Array.partition filterOutErrors
This in principle meets the requirement since values contains all the success cases but understandably the compiler can't infer the types so both values and err contains Result<DataEntry, exn>.
Is there any way to split a list of result Result<Success, Err> such that you end up with separate lists of the inner type?
Is there any way to split a list of result Result<Success, Err> such that you end up with separate lists of the inner type?
Remember that Seq / List / Array are foldable, so you can use fold to convert a Seq / List / Array of 'Ts into any other type 'S. Here you want to go from []Result<DataEntry, exn> to, e.g., the tuple list<DataEntry> * list<exn>. We can define the following folder function, that takes an initial state s of type list<'a> * list<'b> and a Result Result<'a, 'b> and returns your tuple of lists list<'a> * list<'b>:
let listFolder s r =
match r with
| Ok data -> (data :: (fst s), snd s)
| Error err -> (fst s, err :: (snd s))
then you can fold over your array as follows:
let (values, err) = Seq.fold listFolder ([], []) allData
You can extract the good and the bad like this.
let values =
allData
|> Array.choose (fun r ->
match r with
| Result.Ok ok -> Some ok
| Result.Error _ -> None)
let err =
allData
|> Array.choose (fun r ->
match r with
| Result.Ok _ -> None
| Result.Error error -> Some error)
You seem confused about whether you have arrays or lists. The F# code you use, in the snippet and in your question text, all points to use of arrays, in spite of you several times mentioning lists.
It has recently been recommended that we use array instead of the [] symbol in types, since there are inconsistencies in the way F# uses the symbol [] to mean list in some places, and array in other places. There is also the symbol [||] for arrays, which may add more confusion.
So that would be recommending Result<DataEntry,exn> array in this case.
The answer from Víctor G. Adán is functional, but it's a downside that the API requires you to pass in two empty lists, exposing the internal implementation.
You could wrap this into a "starter" function, but then the code grows, requires nested functions or using modules and the intention is obscured.
The answer from Bent Tranberg, while more readable requires two passes of the data, and it seems inefficient to map into Option type just to be able to filter on it using .Choose.
I propose KISS'ing it with some good old mutation.
open System.Collections.Generic
let splitByOkAndErrors xs =
let oks = List<'T>()
let errors = List<'V>()
for x in xs do
match x with
| Ok v -> oks.Add v
| Error e -> errors.Add e
(oks |> seq, errors |> seq)
I know I know, mutation, yuck right? I believe you should not shy away from that even in F#, use the right tool for every situation: the mutation is kept local to the function, so it's still pure. The API is clean just taking in the list of Result to split, there is no concepts like folding, recursive calls, list cons pattern matching etc. to understand, and the function won't reverse the input list, you also have the option to return array or seq, that is, you are not confined to a linked list that can only be appended to in O(1) in the head - which in my experience seldom fits well into business case, win win win in my book.
I general, I hope to see F# grow into a more multi-paradigm programming language in the community's mind. It's nice to see these functional solutions, but I fear they scare some people away unnecessarily, as F# is already multi-paradigm!

F# pattern matching with optional list of tuples

I'm trying to use pattern matching for an optional list of tuples but I could not write an exhaustive matching expression despite trying everything I can think of.
I'm struggling to understand why the F# compiler is insisting that my patterns in the following examples are not exhaustive.
module Mapper.PatternMatchingOddity
type A = A of string
type B = B of string
type ProblemType = ProblemType of (A * B) list option
//Incomplete pattern matches on this expression. Some ([_;_]) may indicate a case...
let matchProblem = function
|Some [(x:A,y:B)] -> []
|Some ([_,_]) -> [] //rider says this rule will never be matched
|None -> []
//same as before
let matchProblem1 = function
|Some [_,_] -> []
|Some [] -> []
//|Some _ -> []//this removes the warning but what is the case not covered by the previous two?
|None -> []
let matchProblem2 (input:ProblemType) =
match input with //same as before
|ProblemType (Some [(x:A,y:B)]) -> []
|ProblemType None -> []
How do I write the exhaustive matching and what am I missing above? Can you give an example for an input that would be accepted as a valid parameter to these functions and slip through the patterns?
Great question! I think many people that start out with F# grapple with how lists, options and tuples interact. Let me start by saying: the compiler is correct. The short answer is: you are only matching over singleton lists. Let me try to explain that a little deeper.
Your type is ('a * 'b) list option, essentially. In your case, 'a and 'b are themselves a single-case discriminated using of a string. Let's simplify this a bit and see what happens if we look at each part of your type in isolation (you may already know this, but it may help to put it in context):
First of all, your type is option. This has two values, None or Some 'a. To match over an option you can just do something like
match o with
| Some value -> value
| None -> failwith "nothing"`
Next, your type is a list. The items in a list are divided by semicolons ;. An empty list is [], a singleton list (one with a single item) is [x] and multiple items [x;y...]. To add something to the start of a list use ::. Lists are a special type of discriminated union and the syntax to match over them mimics the syntax of lists construction:
match myList with
| [] -> "empty"
| [x] -> printfn "one item: %A" x
| [x; y] -> printfn "two items: %A, %A" x y
| x::rest -> printfn "more items, first one: %A" x
Third, your list type is itself a tuple type. To deconstruct or match over a tuple type, you can use the comma ,, as with match (x, y) with 1, 2 -> "it's 1 and 2!" ....
Combine all this, we must match over an option (outer) then list (middle) then tuple. Something like Some [] for an empty list and None for the absence of a list and Some [a, b] for a singleton list and Some (a,b)::rest for a list with one or more items.
Now that we have the theory out of the way, let's see if we can tackle your code. First let's have a look at the warning messages:
Incomplete pattern matches on this expression. Some ([_;_]) may indicate a case...
This is correct, the item in your code is separated by , denoting the tuple, and the message says Some [something; something] (underscore means "anything"), which is a list of two items. But it wouldn't help you much to add it, because the list can still be longer than 2.
rider says this rule will never be matched
Rider is correct (which calls the FSC compiler services underneath). The rule above that line is Some [(x:A,y:B)] (the :A and :B are not needed here), which matches any Some singleton array with a tuple. Some [_,_] does the same, except that it doesn't catch the values in a variable.
this removes the warning but what is the case not covered by the previous two?
It removes the warning because Some _ means Some with anything, as _ means just that: it is a placeholder for anything. In this case, it matches the empty list, the 2-item list, the 3-item list the n-item list (the only one your match is the 1-item list in that example).
Can you give an example for an input that would be accepted as a valid parameter
Yes. Valid input that you were not matching is Some [] (empty list), Some [A "a", B "x"; A "2", B "2"] (list of two items) etc.
Let's take your first example. You had this:
let matchProblem = function
|Some [(x:A,y:B)] -> [] // matching a singleton list
|Some ([_,_]) -> [] // matches a singleton list (will never match, see before)
|None -> [] // matches None
Here's what you (probably) need:
let notAProblemAnymore = function
// first match all the 'Some' matches:
| Some [] -> "empty" // an empty list
| Some [x,y] -> "singleton" // a list with one item that is a tuple
| Some [_,a;_,b] -> "2-item list" // a list with two tuples, ignoring the first half of each tuple
| Some ((x,y)::rest) -> "multi-item list"
// a list with at least one item, and 'rest' as the
// remaining list, which can be empty (but won't,
// here it has at least three items because of the previous matches)
| None -> "Not a list at all" // matching 'None' for absence of a list
To sum it up: you were matching over a list that had only one item and the compiler complained that you missed lists of other lengths (empty lists and lists that have more than one item).
Usually it is not necessary to use option with a list, because the empty list already means the absence of data. So whenever you find yourself writing the type option list consider whether just list would suffice. It will make the matching easier.
You are struggling because your example is too “example”.
Let’s convert your example to a more meaningful one: check the input, so that
If it is none then print “nothing”, otherwise:
If it has zero element then print “empty”
If it has only one element then print “ony one element: ...”
If it has two elements then print “we have two elements: ...”
If it has three elements then print “there are three elements: ...”
If it has more than three elements then print “oh man, the first element is ..., the second element is ..., the third element is ..., and N elements more”
Now you can see that your code only covers the first 3 cases. So the F# compiler was correct.
To rewrite the code:
let matchProblem (ProblemType input) =
match input with
| None -> printfn "nothing"
| Some [] -> ...
| Some [(x, y)] -> ...
| Some [(x1, y1); (x2, y2)] -> ...
| Some [(x1, y1); (x2, y2); (x3, y3)] -> ...
| Some (x1, y1) :: (x2, y2) :: (x3, y3) :: rest -> // access rest.Length to print the number of more elements
Notice that I’m using pattern matching on the parameter ProblemType input so that I can extract the input in a convenient way. This makes the later patterns simpler.
Personally, when I learned F#, I didn’t understand many features/syntax until I used them in production code.

Find the length of the longest substring

I see questions similar like this ones, but eventually, for different programming languages. I'm trying to solve this little problem:
Given a string, find the length of the longest substring without
repeating characters. For example, the longest substring without
repeating letters for abcabcbb is abc, which the length is 3. For
bbbbb the longest substring is b, with the length of 1.
I don't need the anwer to it but why what I have so far fails in the second iteration.
1> longest_substring:main("abcabcbb").
H: 97, T: "bcabcbb", Sub: []
Is 97 in []? false
H: 98, T: "cabcbb", Sub: 97
** exception error: no function clause matching string:chr(97,98,1) (string.erl, line 99)
in function longest_substring:process/2 (src/leetcode/algorithms/longest_substring.erl, line 28)
2>
This is the source code:
-module(longest_substring).
-export([main/1]).
-spec main(S :: string()) -> string().
%%%==================================================================
%%% Export
%%%==================================================================
main(S) -> process(S, "").
%%%==================================================================
%%% Internal
%%%==================================================================
process([], Sub) -> string:len(Sub);
process([H | T], Sub) ->
io:format("H: ~w, T: ~p, Sub: ~p~n", [H, T, Sub]),
Found = string:chr(Sub, H),
io:format("Is ~w in ~p? ~p~n", [H, Sub, Found =/= 0]),
% Don't know how to make this `if` thing better...
if
Found > 0 -> process(T, H);
_ -> process(T, string:concat(Sub, H))
end.
You have two places where you are treating character H as a string, both within the if:
if
Found > 0 -> process(T, H);
_ -> process(T, string:concat(Sub, H))
end.
Both appearances of H here need to be [H] instead, to form a string from the single character. (Also, your final clause in the if needs to use true, not an underscore — you should be getting a compiler error about this.)
Currently your solution returns a number, not a string. It also fails to remember any longer substring that might appear early in the string. To fix that, you need to remember the longest substring you've seen so far, which means you need another accumulator:
-module(longest_substring).
-export([main/1]).
-spec main(S :: string()) -> string().
main(S) -> process(S, {0,[]}, {0,[]}).
process([], {LL,Last}, {LG,_}) when LL > LG -> Last;
process([], _, {_,Long}) -> Long;
process([H | T], {LL,Last}=Sub, {LG,_}=Long) ->
case string:rchr(Last, H) of
0 ->
process(T, {LL+1,string:concat(Last,[H])}, Long);
N ->
NewLast = {1+LL-N,string:substr(Last,N+1)++[H]},
process(T, NewLast,
case LL > LG of
true ->
Sub;
false ->
Long
end)
end.
The main/1 function passes two accumulators to process/3, each of which is a pair of a length and a list. The first accumulator tracks the current substring, and the second tracks the longest substring seen so far.
In the last clause of process/3, we first check if H is in the current substring; if not, we add it to the current substring, increase its length by 1, and call process/3 again with the tail of the string. But if H is found in the current substring, we calculate the new current substring using the return value of string:rchr/2 to preserve the longest portion of the previous substring that we can (the original solution does not do this). We then check to see if the length of the current substring is greater than the current longest substring, and if so, we make it the longest substring, or if not we throw it away and keep the current longest substring, and then continue with the tail of the string. (Note that we could also make this check for greater or equal instead of greater; this would make our function return the last longest substring we find rather than the first.)
The first two clauses of process/3 handle the case where the input string has been fully processed. They just decide if the current substring is longer than the longest seen so far and return the longer of the two. (The alternative of using a greater or equal comparison applies here as well.)
for fun, I propose you to avoid complex search. In this solution I create a process for each element of the list holding: the element itself, the Pid of the next process/element in the list, and the Pid of the caller.
To initiate the search, I send to each process/element an empty list.
Each time a process/element receives a list, it checks if its stored element is a member of the received list. If yes, the list is send back to the caller, if not the element is prepend to the list and the new list is sent to the next process/element to continue the evaluation.
The caller process simply waits for as many returned messages as it has sent.
I have added a stop message and a special case for the last element of the list.
-module (longer).
-compile([export_all]).
char_proc(V,Next,Caller) ->
receive
stop -> ok;
Str ->
case lists:member(V,Str) of
true -> Caller ! Str;
false -> send(Next,Caller,[V|Str])
end,
char_proc(V,Next,Caller)
end.
send(noproc,Caller,Str) -> Caller ! Str;
send(Next,_,Str) -> Next ! Str.
find(Str) ->
Me = self(),
Pids = tl(lists:reverse(lists:foldl(fun(X,Acc) -> Pid = spawn(?MODULE,char_proc,[X,hd(Acc),Me]), [Pid|Acc] end,[noproc],Str))),
[X ! [] || X <- Pids],
R = receive_loop(0,[],length(Str)),
[X ! stop || X <- Pids],
R.
receive_loop(N,S,0) -> {N,S};
receive_loop(N,S,I) ->
receive
M when length(M) > N ->
receive_loop(length(M),M,I-1);
_ ->
receive_loop(N,S,I-1)
end.
tested in the shell:
1> c(longer).
{ok,longer}
2> longer:find("abcdad").
{4,"abcd"}
3> longer:find("abcdadtfrseqgepz").
{9,"adtfrseqg"}
4> longer:find("aaaaaaaaaaaa").
{1,"a"}
5> longer:find("abcdatfrseqgepz").
{11,"bcdatfrseqg"}
6>
Note there is no guarantee about witch sub-string will be returned if it exists several solutions, it is very easy to modify the code to return either the first sub-string or all of them.

Convert a string representation of a tuple to a real tuple

How to convert this string "[{type,a},{to,room01023123},{body,hey what's up mister},{by,someone}]" into a tuple like this [{"type","a"},{"to","room01023123"},{"body","hey what's up mister"},{"by","someone"}]
If you need to read from file, just use file:consult
-spec consult(Filename) -> {ok, Terms} | {error, Reason}
Otherwise you can use erl_parse module combined with erl_scan for this. In the simplest case like this
{ok, Tokens, _Line} = erl_scan:string("{hello, world}."),
erl_parse:parse_term(Tokens).
And don't forget that terms should end with full stop.

Pattern matching on bson tuples

The bson-erlang module turns BSON-encoded JSON such as this:
{ "salutation" : "hello",
"subject" : "world" }
Into an Erlang tuple like this:
{ salutation, <<"hello">>, subject, <<"world">> }
Now, the server I'm attempting to talk to can put those fields in any order, and there might be extra fields in there that I don't care about, so -- equally validly -- I might see this instead:
{ subject, <<"world">>, salutation, <<"hello">>, reason, <<"nice day">> }
Is there any way that I can specify a function pattern that extracts a particular piece of the tuple, based on the one appearing immediately before it?
If I try the following, it fails with "no function clause matching..." because the arity of the tuple is wrong, and because the fields that I care about aren't in the correct place:
handle({ salutation, Salutation, _, _ }) -> ok.
Is this possible? Is there a better way to do this?
T = { subject, <<"world">>, salutation, <<"hello">>, reason, <<"nice day">> },
L = size(T),
L1 = [{element(I,T),element(I+1,T)} || I <- lists:seq(1,L,2)].
[{subject,<<"world">>},
{salutation,<<"hello">>},
{reason,<<"nice day">>}]
proplists:get_value(salutation,L1).
<<"hello">>
and if you want all in 1:
F = fun(Key,Tup) -> proplists:get_value(Key,[{element(I,Tup),element(I+1,Tup)} || I <- lists:seq(1,size(Tup),2)]) end.
F(reason,T).
<<"nice day">>
F(foo,T).
undefined
There is no pattern that successfully matches values from a variable-length structure after a prefix of an unknown length. This is true for tuples, lists and binaries. Indeed, such a pattern would require to recurse through the structure.
A common approach for a list is to recurse by splitting head and tail, something typical of functional languages.
f_list([salutation, Salutation | _]) -> {value, Salutation};
f_list([_Key, _Value | Tail]) -> f_list(Tail);
f_list([]) -> false.
Please note that this function may fail if the list contains an odd number of elements.
The same approach is possible with tuples, but you need guards instead of matching patterns as there is no pattern to extract the equivalent of the tail of the tuple. Indeed, tuples are not linked lists but structures with a O(1) access to their elements (and their size).
f_tuple(Tuple) -> f_tuple0(Tuple, 1).
f_tuple0(Tuple, N) when element(N, Tuple) =:= salutation ->
{value, element(N + 1, Tuple)};
f_tuple0(Tuple, N) when tuple_size(Tuple) > N -> f_tuple0(Tuple, N + 2);
f_tuple0(_Tuple, _N) -> false.
Likewise, this function may fail if the tuple contains an odd number of elements.
Based on elements in the question, the advantage of guards over bson:at/2 is unclear, though.

Resources