I'm looking for help with a problem. I'm trying to write a function that passes both a list and function in ML. Basically what the program is supposed to do is take a list and run each element through the function. If the function returns true, then the element is added to a list and the list returned once the function has finished executing. Here's my code:
fun select(x:list, funct)= (* Define a new function that accepts a list and the prime function as a parameter*)
while (tl(x) not nil) do( (*While the tail is not empty*)
if funct(hd(x)) then (*Then run the function with the the head*)
val l = l::hd(x) (*Adds the head of x to the list *)
(*else 1+tl(x)*));
Any help would be very much appreciated.
A few pointers:
You pretty much never use loops in ML. Any time you need to iterate, write a recursive function.
You rarely need to specify types. In this case ML can infer, from the fact that you're calling tl(x), that x must be a list.
Instead of using hd(x) and tl(x) to decompose the list, you generally do this with pattern matching in the function arguments. Instead of a single argument x, write the argument as x::xs; x will be assigned to the head of the list, and xs to the tail.
Instead of using conditional statements to check the structure of your argument (in this case, whether your list is empty or not), you can write multiple function definitions with different patterns. ML will try them one by one until it finds one that fits.
The body of your function needs to be an expression which evaluates to your return value. Everything in ML is an expression; even if x then a else b is essentially a function which returns either a or b.
Keeping all this in mind, here's something to get you started:
fun select([], funct) = []
| select(x::xs, funct) = ...
The two cases here replace your while condition - the first will be evaluated only when your list is nil. The pattern in the second case automatically assigns values to the head and tail of your list. This definition is intended to be recursive; select([],funct)=[] is your base case, and select(x::xs,funct)=... should include a call to select(xs,funct).
take a list and run each element through the function. If the function returns true, then the element is added to a list and the list returned once the function has finished executing.
This is exactly the built-in List.filter function. No need to reinvent the wheel.
Related
I'm trying to create a list of unique by appending to a list, but I'm getting this error.
Error: This expression has type 'a list
but an expression was expected of type unit
in_list is a boolean function that checks whether the value is in the list.
if(in_list x seen_list) then print_string("Already found") else seen_list#x in
List.iter uniq check_list;;
It seems like there must be some small syntactic error I need to fix for the append function. Suggestions?
TL;DR: Lists are immutable in OCaml
According to your code, you seem to believe that lists are mutable in OCaml, and they are not. Hence seen_list#x compute a new list but does not change seen_list.
You could change your code to
let uniq seen_list x =
if in_list x seen_list then
(Printf.printf: "uniq: %d: Already seen.\n" x; seen_list)
else x :: seen_list
in
List.fold_left uniq [] check_list
The uniq function maps a list of integers to a list of integers without repetitions, logging the entries it skips.
This code is obviously intended to be learning material, I guess, nevertheless you should be aware that it most likely implements a Shlemiel the painter's algorithm.
This is a type error, not a syntactic error.
An OCaml function must always return a result of the same type. Right now, when the item is in the list your function tries to return a different type than if the item is not in the list.
Specifically, when the item is already there your function calls print_string, which returns (). This is called unit, and is a placeholder representing no interesting value. When the item isn't already there, your function returns a value of type 'a list. Almost certainly what you need to do is to return a list in all cases.
It's hard to say more without seeing more of your code, but the most usual way to handle this situation is to return the old list when the item is already there and a new, longer list when the item isn't already there.
Update
There are many things to fix in this code, but that's the point of the exercise I assume.
Your next problem seems to be that List.iter is an imperative function, i.e., it wants to do something rather than produce a result. Hence the function that it iterates over the list should return unit (described above). You're using the function uniq instead, which returns a list.
If you want to use a higher-order function like List.iter, which is excellent OCaml style, you will need to use a fold (List.fold_left or List.fold_right), whose purpose is to accumulate a result.
I just started learning Erlang so please bear with me if this question seems a little simple.
Hi guys. I've been thinking about it for a while but nothing I come up with seems to be working.
I am writing an Erlang function that is supposed to take a list as an argument then print the list with my name in front of it. For the purposes of this question, let's say my name is "James".
If I type in testmodule:NameInFront("Legible", "Hey", "Think").
Erlang should return ["James", "Legible", "Hey", "Think"]
This is the code I have so far:
-module(testmodule).
-export([NameInFront/1]).
NameInFront(List)-> ["James"]++[List].
It works just fine when I type in just one word, which I guess it the fault of the NameInFront/1 part but I want it to be able to handle any amount of words I type in. Anyone know how I can get my function to handle multiple inputs? Thank you very much.
I'm not quite sure what you mean: whether you want your function to be variadic (take a flexible number of arguments), or you are having trouble getting your lists to join together properly.
Variadic functions are not the way Erlang works. FunctionName/Arity defines the concrete identity of a function in Erlang (discussed here). So our way of having a function take multiple arguments is to make one (or more) of the arguments a list:
print_terms(Terms) -> io:format("~tp~n", [Terms]).
The io:format/2 function itself actually takes a list as its second function, which is how it deals with a variable number of arguments:
print_two_things(ThingOne, ThingTwo) ->
io:format("~tp~n~tp~n", [ThingOne, ThingTwo]).
In your case you want to accept a list of things, add your name to it, and print it out. This is one way to do it.
name_in_front(ListOfStrings) ->
NewList = ["James" | ListOfStrings],
io:format("~p~n", [NewList]).
Using the ++ operator is another (which is actually a different syntax for a recursive operation which expands to the exact same thing, ):
name_in_front(ListOfStrings) ->
NewList = ["James"] ++ ListOfStrings,
io:format("~tp~n", [NewList]).
But that's a little silly, because it is intended to join two strings together in a simple way, and in this case it makes the syntax look weird.
Yet another way would be to more simply write a function that take two arguments and accomplishes the same thing:
any_name_in_front(Name, ListOfThings) ->
io:format("~tp~n", [[Name | ListOfThings]]).
The double [[]] is because io:format/2 takes a list as its second argument, and you want to pass a list of one thing (itself a list) into a single format substitution slot (the "~tp" part).
One thing to note is that capitalization matters in Erlang. It has a meaning. Module and function names are atoms, which are not the same thing as variables. For this reason they must be lowercase, and because they must be lowercase to start with the convention is to use underscores between words instead of usingCamelCase. Because, well, erlangIsNotCpp.
Play around in the shell a bit with the simple elements of the function you want, and once you have them ironed out write it into a source file and give it a try.
For an assignment, I have to create a type inference relation. here's the approach I used
tuples([]).
tuples(_|_).
type(tuples([]),tuples([])).
type(tuples(X|T),tuples(Y|Z)) :- type(tuples(T),tuples(Z)),type(X,Y).
I have already defined the type relation for all possible terms required for my assignment where y is the type of X in type(X,Y). For defining types of n-tuples, I used the approach similiar to the one used for appending lists.
But prolog always returns false when I ask
?-type(tuples([3,str]),Z)
or even
?-type(tuples([3,str]),tuples(Z))
or
?-type(tuples([3,str,4,abc,5,6]),Z)
i.e a list of length n, the answer returned is false.
Nothing changed even when I revered the sub-rules in the last rule.
tuples([]).
tuples(_|_).
type(tuples([]),tuples([])).
type(tuples(X|T),tuples(Y|Z)) :- type(X,Y),type(tuples(T),tuples(Z)).
I am not asking for alternative approaches to type of tuples to help me in my assignment but I can't figure out why this approach is not working.
It looks like your definition of a tuple is a List with length 2.
This rule does not check for that:
tuples(_|_).
What you probably want is this:
tuples([_,_]).
If you want it to check for any length list, use:
tuples([_|_]).
In the latter rule, the first wildcard represents the first item in the list (the head) and the second wildcard represents the rest of the list (the tail).
I'm a newbie to Haskell, I have a problem. I need to write a function that splits a list into a list of lists everywhere a 'separation' appears.
I will try to help you develop the understanding of how to develop functions that work on lists via recursion. It is helpful to learn how to do it first in a 'low-level' way so you can understand better what's happening in the 'high-level' ways that are more common in real code.
First, you must think about the nature of the type of data that you want to work with. The list is in some sense the canonical example of a recursively-defined type in Haskell: a list is either the empty list [] or it is some list element a combined with a list via a : list. Those are the only two possibilities. We call the empty list the base case because it is the one that does not refer to itself in its definition. If there were no base case, recursion would never "bottom out" and would continue indefinitely!
The fact that there are two cases in the definition of a list means that you must consider two cases in the definition of a function that works with lists. The canonical way to consider multiple cases in Haskell is pattern matching. Haskell syntax provides a number of ways to do pattern matching, but I'll just use the basic case expression for now:
case xs of
[] -> ...
x:xs' -> ...
Those are the two cases one must consider for a list. The first matches the literal empty list constructor; the second matches the element-adding constructor : and also binds two variables, x and xs', to the first element in the list and the sublist containing the rest of the elements.
If your function was passed a list that matches the first case, then you know that either the initial list was empty or that you have completed the recursion on the list all the way past its last element. Either way, there is no more list to process; you are either finished (if your calls were tail-recursive) or you need to pass the basic element of your answer construction back to the function that called this one (by returning it). In the case that your answer will be a list, the basic element will usually be the empty list again [].
If your function was passed a list that matches the second case, then you know that it was passed a non-empty list, and furthermore you have a couple of new variables bound to useful values. Based on these variables, you need to decide two things:
How do I do one step of my algorithm on that one element, assuming I have the correct answer from performing it on the rest of the list?
How do I combine the results of that one step with the results of performing it on the rest of the list?
Once you've figured the answers to those questions, you need to construct an expression that combines them; getting the answer for the rest of the list is just a matter of invoking the recursive call on the rest of the list, and then you need to perform the step for the first element and the combining.
Here's a simple example that finds the length of a list
listLength :: [a] -> Int
listLength as =
case as of
[] -> 0 -- The empty list has a length of 0
a:as' -> 1 + listlength as' -- If not empty, the length is one more than the
-- length of the rest of the list
Here's another example that removes matching elements from a list
listFilter :: Int -> [Int] -> Int
listFilter x ns =
case ns of
[] -> [] -- base element to build the answer on
n:ns' -> if n == x
then listFilter x ns' -- don't include n in the result list
else n : (listFilter x ns') -- include n in the result list
Now, the question you asked is a little bit more difficult, as it involves a secondary 'list matching' recursion to identify the separator within the basic recursion on the list. It is sometimes helpful to add extra parameters to your recursive function in order to hold extra information about where you are at in the problem. It's also possible to pattern match on two parameters at the same time by putting them in a tuple:
case (xs, ys) of
([] , [] ) -> ...
(x:xs', [] ) -> ...
([] , y:ys') -> ...
(x:xs', y:ys') -> ...
Hopefully these hints will help you to make some progress on your problem!
Let's see if the problem can be reduced in a obvious way.
Suppose splitList is called with xs to split and ys as the separator. If xs is empty, the problem is the smallest, so what's the answer to that problem? It is important to have the right answer here, because the inductive solution depends on this decision. But we can make this decision later.
Ok, so for problem to be reducable, the list xs is not empty. So, it has at least a head element h and the smaller problem t, the tail of the list: you can match xs#(h:t). How to obtain the solution to the smaller problem? Well, splitList can solve that problem by the definition of the function. So now the trick is to figure out how to build the solution for bigger problem (h:t), when we know the solution to the smaller problem zs=splitList t ys. Here we know that zs is the list of lists, [[a]], and because t may have been the smallest problem, zs may well be the solution to the smallest problem. So, whatever you do with zs, it must be valid even for the solution to the smallest problem.
splitList [] ys = ... -- some constant is the solution to the smallest problem
splitList xs#(h:t) ys = let zs = splitList t ys
in ... -- build a solution to (h:t) from solution to t
I don't know how to test it. Anybody tells me how to write a function to a .hs file and use winGHCi to run this function?
WinGHCi automatically associates with .hs files so just double-click on the file and ghci should start up. After making some changes to the file using your favourite editor you can write use the :r command in ghci to reload the file.
To test the program after fixing typos, type-errors, and ensuring correct indentation, try calling functions you have defined with different inputs (or use QuickCheck). Note Maybe is defined as Just x or Nothing. You can use fromMaybe to extract x (and provide default value for the Nothing case).
Also try to make sure that pattern matching is exhaustive.
Let's say I have these facts:
parent(bob, sam). %bob is sam's parent
parent(sara, sam). %sara is sam's parent
I wanted to find out who were sam's parents and return them in a list and as such used:
list_parents(P, L) :- findall(Parent, parent(Parent, P), L).
What I want to do now is ask the same question but with only one argument as such:
findParents(sam).
I tried:
findParents(Name) :- list_parents(Name, L).
but this way Prolog simply answers "True".
The thing with prolog is that it's a little different than most languages (understatement, if there every was one):
All variables are locally scoped.
Variable values are invariant once bound (unified), unless backtracking unbinds it.
Predicates do not return a value in the conventional sense. They either succeed or fail.
To get value back from testing a predicate, you evaluate the predicate passing it something from your predicate. It doesn't matter if you pass it a variable or a bound value: the called predicate will succeed or value if what the caller has unifies with what you passed it. If you passed a variable, and the called predicate unifies it with a non-variable value, your variable is bound to that value. Think of it (somewhat) as if you had a procedural language where every function returned bool and all parameter values were passed by reference.
What you tried worked:
findParents(Name) :- list_parents(Name, L).
The variable L was unified with (was bound to) the list returned by findall/3. And then it went out of scope.
If you want to actually do something with that returned (bound) value, you need to deal with it where it's in-scope, or unify that value with something that that predicate was invoked with and thus pass it up the call stack. Or, you could assert it into the database of facts and save it for later.
The way prolog works is that the root predicate used to start your "program" defines a search tree in terms of the predicates in your database. Prolog's "engine" then performs a depth-first, left-to-right search of that tree. Your predicate succeeds when the engine gets to a leaf node of the search tree you defined. Backtracking into your predicate causes the engine to look for the next solution in the search tree.
As a result, anything you want to accomplish in a persistent way has to occur as a side effect of the prolog "engine" evaluating a predicate. For instance print() always succeeds just once (when you enter the box)...and as a side effect prints whatever you asked it to print. Backtracking into the print doesn't "undo" the print, but print() doesn't succeed again.
The func library provides a syntax for functions with return values in SWI-Prolog. In this example, you can print all parents of sam by writing writeln(list_parents $ sam):
:- initialization(main).
:- use_module(library(func)).
main :- writeln(list_parents $ sam).
list_parents(P, L) :- findall(Parent, parent(Parent, P), L).
parent(bob, sam). %bob is sam's parent
parent(sara, sam). %sara is sam's parent
Similarly, you can define a function with multiple parameters like this one:
% return a item at an index in a list.
nth0((Index,List),ToReturn) :-
nth0(Index,List,ToReturn).
...and then use it like this:
example :-
ListIndex = (nth0 $(0,[1,2,3,4])), %returns 1, which is the first item in this list
writeln(ListIndex).
you could print the list if want only the user to see it
something like:
findParents(Name):-
list_parents(Name,L),
print(L).
but this isnt exactly returning. remember, in prolog, there are no functions and therefore no "return values". you can simulate a function by writing foo(Args,Return) but you can always call it like foo(X,sam) -sometimes it will give what you want, sometimes it wont, sometimes it will crash.