Say that I have a self made dictionary made from a list of tuples
let menu = [("pizza",17);("hotdog",5);("burger", 12);("drink",3);("milkshake",4)]
I want to write a search function that takes both my dictionary and a key value as a parameter, then returns an option type with the value if key can be found in dict, and None if it can't.
I feel like this is a problem built around f# recursion, using and returning option types as well as obtaining individual values from a tuple, but I'm having a hell of a time putting them together and getting anything that comes even remotely close to accomplishing this task.
I've come up with some pseudo-code that I believe would solve the problem, but actual f# implementation is another story. In an imperative language this seems like a trivial problem, but trying to grasp functional has been really difficult.
//create function `search` accepts dictionary and search key
//match searchkey with dictionary key
//if searchkey = dictionary key, return option type w/ value
//if searchkey <> dictionary key, recurse call next dict values
//if end of dictionary, doesn't exist, return none
//Here's a *very* rough sketch of what I think should be happening.
let rec search dict key =
match dict with
//first check for an empty list, if empty return None
| [] -> None
//next check that there is a head and a tail for dict
//also check for match between first element of head and key
//if match, return hd
//still needs to return option type though, but how?
| hd :: tl when fst hd = key -> snd hd
//finally call search on the tail
| _ :: tl -> search tl key
The empty list condition and the wildcard pattern I'm fairly sure are correct, but it's the actual check and return that im stuck on. How might I go about that particular step?
Patterns can be nested inside other patterns. The tuple pattern (a, b) can be nested inside the list head/tail pattern head :: tail like this: (a, b) :: tail
This means the second pattern match can look like this (k, v) :: _ when k = key.
You need to return an option from every branch, so either a Some x or a None. The second match branch was missing a Some wrapper.
The code with both changes:
let rec search dict key =
match dict with
| [] -> None
| (k, v) :: _ when k = key -> Some v
| _ :: tl -> search tl key
They way to think about recursion, is to just get one example right. And leave the remaining list to the recursive function. And you must somehow accomplish that the "remaining" list gets smaller.
First, you deal with a list. One way to think about it is to just check one element at a time. So you extract the first element of a list, do something with it, then repeat the recursive function on the remaining list. So you could start with:
let search key lst =
match lst with
| head :: tail ->
Think of your example list, in this case. The first invocation of your example list your head would be ("pizza",17).
The next step you now need to-do is. Deconstruct the tuple into key and value and check them. You deconstruct it with
let (k, v) = head
Then you need to check if your k is equal to key. If it is equal, then you want to return the value.
if k = key
then Some v
The else branch must handle the case where your k is not the key you search. This is the recursive step. You want to repeat the checking on the remaining list items.
else search key tail
Remember at this point tail is now your menu with the first element removed. Currently you have the following code.
let rec search key lst =
match lst with
| head :: tail ->
let (k, v) = head
if k = key
then Some v
else search key tail
But this code does not handle the case when it cannot find your item. Think what would happen if the if k = key is never true! It will remove one-element at a time, then recursive on the remaining list until you end up with the empty list.
Empty list then means, you didn't find the key. To be successful you now need to add a case for the empty list. In that case your key is not in your list, and you must return "None". So you end up with:
let rec search key lst =
match lst with
| [] -> None
| head :: tail ->
let (k, v) = head
if k = key
then Some v
else search key tail
Good evening everyone, I'm new to haskell. I'm trying to sum up a list of reading a string Unicode values and store them in a list and then sum the integers up.
getLetterUnicodeValue :: Char -> Int
getLetterUnicodeValue l = (ord l) - 64
unicodeValueList :: String -> [Int]
unicodeValueList x = getLetterUnicodeValue (head x) : unicodeValueList (tail x)
total :: [Int] -> Int
total [] = 0
total x = (head x) + (total (tail x))
I got the error of empty list when the string come to the last character and the sum up function cannot successfully execute. Is there any way to stop the function unicodeValueList when it comes to its end.
*** Exception: Prelude.head: empty list
The surest way to avoid this exception is not to use head. Instead you can use pattern matching to get the head and tail of a list:
unicodeValueList (x:xs) = getLetterUnicodeValue x : unicodeValueList xs
total (x:xs) = x + total xs
This way x and xs will only be available when the list is non-empty and it is guaranteed that you never accidentally access the head or tail of an empty list.
Of course now you'll get a warning that the pattern match is incomplete: You don't specify what should happen when the list is empty. Of course this was true before as well, but now that you use pattern matching the compiler can actually see this and warn you about it (whereas the previous code crashed at runtime without any prior warning).
So what should be done when the list is empty? Well, an empty string contains no unicode values, right? So it should return the empty list when the input is empty:
unicodeValueList [] = []
Of course you don't need pattern matching to fix your error. You could just use an if to make sure that you only call head and tail when the list is not empty. But if you do that, the compiler won't be able to verify that your checks are in order. If you use pattern matching and avoid the unsafe head and tail functions completely, you'll never be able to accidentally access the head or tail of an empty list and the compiler will warn you if you ever forget to consider that the list might be empty.
Yep, you just will have to pattern match in unicodeValueList
unicodeValueList :: String -> [Int]
unicodeValueList [] = []
unicodeValueList (x:xs) = getLetterUnicodeValue x : unicodeValueList xs
Note this could be written more nicely as unicodeValueList = map getLetterUnicodeValue. The reason you are getting the error for head is that your recursion had no base case - it keeps trying to recurse, even when it has reached the empty list.
I'm trying to write a function in ML to delete an entry from a list, given an index.
So, for example, if I have a list L = [1,2,3,4,5] and want to delete 3 from the list, I can call delete(2, L), which should delete the element at index 2, which is 3.
I have a function for deleting from a list, given a specific item in the list, but was wondering how I could get an index from a list.
Below is my code from deleting a specific element from a list
fun delete(element, list_head::list_tail) =
if element = list_head then list_tail
else list_head::delete(element, list_tail);
You can use the pattern matcher to define your two base cases and then implement your delete in terms of these cases.
fun delete (_, nil) = nil
| delete (0, _::xs) = xs
| delete (i, x::xs) = x::del(i-1,xs);
is it possible to define a circular list in erlang?
http://en.wikipedia.org/wiki/Linked_list
first question would be what exactly a circular list mean in erlang?
is it with two elements, one element its self and next to it address to the next element, stored in a list?
if so i can say there is a possibility of defining a circular list in erlang.
but i need clarification weather is it what i think a circular list is in erlang?
There is no built-in list mechanism to do it. However, you can build one using a tuple holding the elements you've visited or not.
The basic structure is a tuple with two lists: {Old, New}. When you first start with an empty list, it looks like {[],[]}. When you fill the list, you fill it in the New list:
new() -> {[], []}.
insert(X, {Old, New}) -> {Old, [X|New]}.
peek({_Old, [H|_]}) -> X.
To move within the list, what you do is first seek in the New list, and put the value in the old one:
next({Old, [H|New]}) -> {[H|Old], New}.
That's fine and it works as if we were just discarding old elements. What happens when we hit the end of the list though? We need to fix the function (and also the peek one):
peek({Old, []}) -> hd(lists:reverse(Old));
peek({_Old, [H|_]}) -> X.
next({Old, []}) ->
{[], lists:reverse(Old)}}.
next({Old, [H|New]}) ->
{[H|Old], New}}.
If there's nothing in the list, it crashes. You could also return 'undefined' if you wanted to by special casing it:
next({[], []}) ->
undefined;
next({Old, []}) ->
{[], lists:reverse(Old)}.
next({Old, [H|New]}) ->
{[H|Old], New}.
This then lets you use the function 'next', 'peek' and possibly 'delete' (see below) to do normal stuff. We could also add a 'prev' function to allow backwards browsing:
prev({[], []}) ->
undefined;
prev({[], New}) ->
{lists:reverse(New), Old}.
prev({[H|Old], New}) ->
{Old, [H|New]}.
delete({Old, []}) -> {[], tl(lists:reverse(Old))};
delete({Old,[H|New]}) -> {Old, New};
And that should cover most of it.
Seeing erlang, and the erlang virtual machine, only supports immutable data it is impossible to build a circular list. If you were to build one yourself in some "illegal" way then it is not certain that the memory management could handle it properly.
There are no circular lists in Erlang supported by the virtual machine. You have to build them yourself if you want one.
Why yes you can ;)
14> X = ll:new().
20496
15> ll:push(X, 1).
1
16> ll:push(X, 2).
2
17> ll:push(X, 3).
3
18> ll:pop(X).
3
19> ll:hd(X).
2
20> {V0,R0} = ll:first(X).
{2,#Ref<0.0.0.80>}
21> {V1,R1} = ll:next(X, R0).
{1,#Ref<0.0.0.76>}
22> {V2,R2} = ll:next(X, R1).
{2,#Ref<0.0.0.80>}
And here is some crappy code to prove it
-module(ll).
-export([new/0, delete/1, push/2, pop/1, first/1, hd/1, next/2]).
-define (META_KEY, '$meta_list').
-record(elt, {id, val, next}).
-record(meta, {id =?META_KEY, size, hd, tl}).
% Returns TID of ETS table representing linked list
new() ->
Tid = ets:new(alist,[{keypos, 2}]),
ets:insert(Tid, #meta{size=0, hd=undefined, tl=undefined}),
Tid.
% Delete list / ETS table representing linked list
delete(AList) ->
ets:delete(AList).
% Returns the value of what was pushed
push(AList, AnElt) ->
#meta{size = Size} = Meta = get_meta(AList),
Hd = get_head(AList, Meta),
Ref = make_ref(),
NewElt = #elt{id=Ref, val=AnElt, next=iif(Size, 0, Ref, Hd#elt.id)},
ets:insert(AList, NewElt),
case Size of
0 -> ets:insert(AList, Meta#meta{size=1,hd=Ref,tl=Ref});
N ->
Tl = get_tail(AList, Meta),
ets:insert(AList, Tl#elt{next = Ref}),
ets:insert(AList, Meta#meta{size=N+1,hd=Ref})
end,
AnElt.
% Returns the value of the popped element
pop(AList) ->
#meta{size = Size} = Meta = get_meta(AList),
Hd = get_head(AList, Meta),
case Size of
0 -> ok;
1 ->
ets:insert(AList, Meta#meta{size=0, hd=undefined,tl=undefined});
N ->
Next = get_next(AList, Hd),
Tail = get_tail(AList, Meta),
ets:insert(AList, Meta#meta{size=N-1, hd=Next#elt.id}),
ets:insert(AList, Tail#elt{next=Next#elt.id})
end,
ets:delete(AList, Hd#elt.id),
Hd#elt.val.
% Returns the value of the first element
hd(AList)->
{First, _Next} =first(AList),
First.
% Returns {val, ptr_to_tail}. The prt_to_tail can be used in next/2
first(AList)->
#meta{size = Size} = Meta = get_meta(AList),
if
Size == 0 -> {undefined, undefined};
true ->
Hd = get_head(AList, Meta),
{Hd#elt.val, Hd#elt.id}
end.
% Given ptr_to_tal, returns {hd(tail), ptr_to_tail}.
next(_AList, undefined) ->
{undefined, undefined};
next(AList, Id) ->
case ets:lookup(AList, Id) of
[] -> {error, node_missing};
[#elt{next=Next}] ->
case ets:lookup(AList, Next) of
[]-> {error, node_missing};
[#elt{val=Value}] ->
{Value, Next}
end
end.
%helper functions
get_meta(List)->
case ets:lookup(List, ?META_KEY) of
[] -> {error, corruptlist};
[Meta] -> Meta
end.
get_head(AList, #meta{size = Size, hd=Hd} ) ->
case Size of
0 -> #elt{};
_N ->
case ets:lookup(AList, Hd) of
[] -> {error, corruptlist};
[Head] -> Head
end
end.
get_tail(AList, #meta{size = Size, tl=Tl} ) ->
case Size of
0 -> #elt{};
_N ->
[Tail] = ets:lookup(AList, Tl),
Tail
end.
get_next(_AList, #elt{next=undefined}) -> #elt{};
get_next(AList, #elt{next=Next}) ->
case ets:lookup(AList, Next) of
[] -> {error, corruptlist};
[Elt] -> Elt
end.
iif(A, B, TruePart, ElsePart)->
case A == B of
true -> TruePart;
false -> ElsePart
end.
As pointed out above, you would have to implement them yourself. But as you can associate data to other data in various ways in erlang there is nothing stopping you from doing so.
Essentially you need just one thingie representing the current index and another one representing the pointer to the next index. One funny way would be starting a process for each element in the list pointing to the next(or previous) process(element) by its PID. One (or many) special purpose process(es) could be crawling those other "list"-processes. Less crazy aproaches might make use of ets or mnesia.
Hey, I'm trying to learn some f# basics and am stumbling along. I'm wondering how you would go about "replacing" the first element in a list.
Any help would be appreciated!
Here's a general purpose function. It will replace the head of a list with a new value if the list is non-empty, else it will return a single element list with the replace value.
let replaceHead newHead list =
match list with
| _ :: tail -> newHead :: tail
| [] -> [newHead]
You could 'cons' (using the ::-operator) the new first element to the tail (List.tail) of the original list:
let theList = [1; 2; 3; 4]
let firstReplaced = 0 :: (List.tail a)
Note that this will leave the original list (theList) untouched.