I am working on SML/NY project and I have a datatype expression:
datatype expression = Constant of int |
Variable of string |
Operator of string * expression |
Pair of expression list |
List of expression list
I created a function that sum constants in expression (doesn't work for List yet):
fun cons [] = 0
| cons (l) =
case (hd l) of
Constant a => (a + cons (tl l))
| Operator ("*", Pair [Constant a, Constant b]) => (a*b + cons (tl l))
| Operator ("*", List _) => (0 + cons (tl l))
| _ => (0 + cons (tl l))
And now I'm building a function that join all Constant expressions in one:
fun joinSimilar (e:expression) =
case e of
Operator ("+", List (l)) => Operator ("+", List [
Operator ("*",List [Constant (cons (l))])
])
| _ => Constant 0
As far as I understand SML this seems as correct functions. But when I test:
joinSimilar(joinSimilar (Operator ("+", List [
Constant 1,
Operator ("*", Pair [Constant 3, Constant 1]),
Operator ("*", Pair [Constant 5, Variable "x"]),
Variable "x",
Operator ("*", List [Variable "x", Constant 3]),
Operator ("*", List [Variable "x", Variable "x"])])));
I get:
val it = Operator ("+",List [Operator ("*",List [Constant 0])]) : expression
which is not OK, because I should get Constant 4. The trick is, when I test only cons function
cons ([Constant 1,
Operator ("*", Pair [Constant 3, Constant 1]),
Operator ("*", Pair [Constant 5, Variable "x"]),
Variable "x",
Operator ("*", List [Variable "x", Constant 3]),
Operator ("*", List [Variable "x", Variable "x"])]);
I get 4 and that is the right result. Why I get 0 in the first example?
Please help, I tried everything and my confusion is growing from minute to minute. Is that a problem of Sublime, which I am using?
Related
I am working on creating a function called repeat that takes two int lists lst1 and lst2. Assume that lst2 only has nonnegative integers, repeats the integers in the first list lst1 according to the numbers indicated by the second list lst2. If both lists are empty, return an empty list. You may need a local function.
Example:
repeat ([1,2,3], [4,0,3]) -> [1,1,1,1,3,3,3]
I am having a little trouble with getting started with this function. What should I put after the xs?
fun repeat(lst1, lst2) =
case lst1 of
[] => []
| x::xs' => [] (* what should I put here *)
Like any recursion problem, what's your base case? I'd say in this case it's both lists are empty and it gives you an empty list.
fun repeat([], []) = []
What if one is empty but the other isn't? That's a failure. Let's define an exception we can throw if this happens.
exception MismatchedArguments;
fun repeat([], []) = []
| repeat([], _) = raise MismatchedArguments
| repeat(_, []) = raise MismatchedArguments
Now the real question is what we do the rest of the time. Fortunately, SML makes it easy to pattern match both lists and extract their first elements.
exception MismatchedArguments;
fun repeat([], []) = []
| repeat([], _) = raise MismatchedArguments
| repeat(_, []) = raise MismatchedArguments
| repeat(x::xs, y::ys) = ...
At this point, we need a recursive function to repeat an element of the list a certain number of times. As with the overall function, here we see the two hallmarks of recursion: at least one base "exit" condition, and an update step where we converge toward the base condition by updating n to n - 1.
exception MismatchedArguments;
fun repeat([], []) = []
| repeat([], _) = raise MismatchedArguments
| repeat(_, []) = raise MismatchedArguments
| repeat(x::xs, y::ys) =
let
fun repeat'(_, 0) = []
| repeat'(x, n) = x :: repeat'(x, n - 1)
in
...
end
Now, we just need to put it all together, by feeding x and y to repeat' and then concatenating that with the result of calling repeat again with xs and ys. By doing this, we converge down toward the base case of repeat([], []) or we may converge toward a mismatched scenario where a MismatchedArguments exception is raised.
exception MismatchedArguments;
fun repeat([], []) = []
| repeat([], _) = raise MismatchedArguments
| repeat(_, []) = raise MismatchedArguments
| repeat(x::xs, y::ys) =
let
fun repeat'(_, 0) = []
| repeat'(x, n) = x :: repeat'(x, n - 1)
in
repeat'(x, y) # repeat(xs, ys)
end
Now repeat([1, 2, 3], [4, 0, 3]) will yield [1, 1, 1, 1, 3, 3, 3].
New to SML and trying to learn through a series of exercises. The function I am trying to write deals with flattening a tree with N children. My approach was to simply take the current NTreeNode and add its value to some list that I would return. Then take its second argument, the list of children, and tack that on to another list, which would be my queue. This queue would serve as all the items I still have left to process.
I tried to do this approach by passing the NTreeList and the list I would return with the initial value in flattenNTree, to a helper function.
However, when I try to process an NTreeNode from my queue it gives me back an NTree and I can't use my first/second functions on that, I need a tuple back from the queue. I just don't understand how to get back a tuple, I tried to use the NTreeNode constructor, but even that's giving me an NTree back.
My question is how can I extract a tuple from the NTree datatype I have defined.
datatype NTree =
NTreeNode of int * NTree list
| EmptyNTree
;
fun first (a, _) = a;
fun second (_, b) = b;
fun processTree queue finalList =
if null queue
then finalList
else processTree ((tl queue)#(second(NTreeNode(hd queue)))) finalList#[first (NTreeNode (hd queue)) ]
;
fun flattenNTree EmptyNTree = []
| flattenNTree (NTreeNode x) = processTree (second x) [(first x)]
;
An example input value:
val t =
NTreeNode (1, [
NTreeNode (2, [
NTreeNode (3, [EmptyNTree]),
NTreeNode (4, []),
NTreeNode (5, [EmptyNTree]),
EmptyNTree
]),
NTreeNode (6, [
NTreeNode (7, [EmptyNTree])
])
]);
It's much easier to take things apart with pattern matching than fiddling around with selectors like first or tl.
It's also more efficient to accumulate a list in reverse and fix that when you're finished than to repeatedly append to the end of it.
fun processTree [] final = reverse final
| processTree (EmptyTree::ts) final = processTree ts final
| processTree ((NTreeNode (v,t))::ts) final = processTree (ts # t) (v :: final)
Your processTree function is missing the case for EmptyNTree and you seem to be trying to add NTree constructors before calling first and second, whereas you need rather to strip them away, as you do in flattenNTree.
Both problems can be fixed by applying pattern matching to the head of the queue:
fun processTree queue finalList =
if null queue
then finalList
else case hd queue of
EmptyNTree => processTree (tl queue) finalList
| NTreeNode v => processTree (tl queue # second v) (finalList # [first v])
;
You might also consider an implementation based on list functionals (although the order of the result is not the same):
fun flattenNTree t = case t of
EmptyNTree => []
| NTreeNode (n, nts) => n :: (List.concat (List.map flattenNTree nts));
Given the tree type
datatype 'a tree = Node of 'a * 'a tree list
| Leaf
you can fold it:
fun fold f e0 Leaf = e0
| fold f e0 (Node (x, ts)) =
let val e1 = f (x, e0)
in foldl (fn (t, e2) => fold f e2 t) e1 ts
end
and flatten it:
fun flatten t =
fold op:: [] t
I'm required to write a function that takes a list and splits it into 2 lists. The first list will hold elements in odd position and 2nd list hold elements in even position. Here's my attempt which gives me the following warning:
Warning: type vars not generalized because of
value restriction are instantiated to dummy types (X1,X2,...)
How to improve this?
fun splt (lst: int list) =
let
fun splt2 (lst: int list, count: int, lst1: int list, lst2: int list) =
if null lst
then []
else if (count mod 2 = 0)
then splt2 (tl lst, count+1, hd lst::lst1, lst2)
else splt2 (tl lst, count+1, lst1, hd lst::lst2)
in
splt2 (lst,1,[],[])
end
Here's a 2nd correct implementation that I found but I'm mainly interested in fixing the 1st one!!
I want to split a list into a tupple of odd and even elements
fun split [] = ([], [])
| split [x] = ([x], [])
| split (x1::x2::xs) =
let
val (ys, zs) = split xs
in
((x1::ys), (x2::zs))
end;
UPDATE: Improvement is just replace
if null lst then
[]
with this:
if null lst then
[lst1]#[lst2]
Here's some feedback for your code:
Give the function a proper name, like split or partition. The connotations that I have for those names are: Splitting (or exploding) takes something and returns one list of sub-components (e.g. string → char list), while partitioning takes a list of something and divides into two based on a predicate (e.g. List.partition), but they're not really set in stone.
Make up some variable names that aren't lst, since this is just an abbreviation of the type - surely redundant when even the type is there. For generic methods, good names can be hard to come by. A lot of ML code uses stuff like xs to imply a generic, plural form.
Ditch the type annotations; you'll get a polymorphic function that reads more easily:
fun split input =
let
fun split' (xys, count, xs, ys) = ...
in
split' (input, 1, [], [])
end
But really, the version you found online has some advantages: Pattern matching ensures that your lists have the right form before the function body is triggered, which minimizes run-time bugs. The functions hd and tl don't.
You could optimize the order of the cases slightly; i.e. list the most common case first. The parenthesis around x::xs and y::ys is unnecessary. Also, the two other cases (of one or zero elements) can be combined for brevity, but it doesn't matter much.
fun split (x1::x2::xs) =
let
val (ys, zs) = split xs
in
(x1::ys, x2::zs)
end
| split rest = (rest, [])
You could also use case-of instead of let-in-end:
fun split (x1::x2::xs) =
(case split xs of
(ys, zs) => (x1::ys, x2::zs))
| split rest = (rest, [])
Lastly, you may want to make this function tail-recursive:
fun split xys =
let fun split' (x1::x2::xs, ys, zs) = split' (xs, x1::ys, x2::zs)
| split' (rest, ys, zs) = (rev (rest # ys), rev zs)
in
split' (xys, [], [])
end
To help get you over the error you are encountering
you need to look at the type of the function which you have given
val splt = fn : int list -> 'a list
and ask yourself what does an 'a list hold?
- val foo = "foo"::(splt[1,2,3,4,5]);
val foo = ["foo"] : string list
- val bar = 52::splt[1,2,3,4,5];
val bar = [52] : int list
it can hold anything, but the compiler cannot tell by itself.
I'm trying to write a program in Coq to parse a relatively simple context-free grammar (one type of parenthesis) and my general algorithm is for the parser to potentially return the remainder of a string. For example, parsing "++]>><<" should return CBTerminated [Incr Incr] ">><<" and then, say a parser that is parsing "[++]>><<" would be able to pick up the ">><<" and continue with that.
So obviously, the string is smaller, but convincing Coq of that is another matter. It is giving me the error
Recursive definition of parseHelper is ill-formed. [...] Recursive call to parseHelper has principal argument equal to "rest'" instead
of "rest".
Which I assume means that it isn't convinced that rest' < input in the way that it's convinced that rest < input. (where < means "is smaller than").
I'd thought of instead returning a count of how many characters to skip, but that seems rather inelegant and uneccessary.
Require Import Coq.Strings.String.
Require Import Coq.Strings.Ascii.
Require Import Coq.Lists.List.
Require Import ZArith.
Open Scope char_scope.
Open Scope list_scope.
Notation " [ ] " := nil (format "[ ]") : list_scope.
Notation " [ x ] " := (cons x nil) : list_scope.
Notation " [ x ; y ; .. ; z ] " := (cons x (cons y .. (cons z nil) ..)) : list_scope.
Inductive BF :=
| Incr : BF
| Decr : BF
| Left : BF
| Right : BF
| In : BF
| Out : BF
| Sequence : list BF -> BF
| While : BF -> BF.
Inductive BF_Parse_Result :=
| UnmatchedOpen
| EOFTerminated (u : list BF)
| CBTerminated (u : list BF) (rest : string).
Definition bind (val : BF) (onto : BF_Parse_Result) :=
match onto with
| UnmatchedOpen => UnmatchedOpen
| EOFTerminated values => EOFTerminated (cons val values)
| CBTerminated values rest => CBTerminated (cons val values) rest
end.
Fixpoint parseHelper (input : string) : BF_Parse_Result :=
match input with
| EmptyString => EOFTerminated nil
| String first rest =>
match first with
| "+" => bind Incr (parseHelper rest)
| "-" => bind Decr (parseHelper rest)
| "<" => bind Left (parseHelper rest)
| ">" => bind Right (parseHelper rest)
| "," => bind In (parseHelper rest)
| "." => bind Out (parseHelper rest)
| "]" => CBTerminated nil rest
| "[" =>
match parseHelper rest with
| UnmatchedOpen => UnmatchedOpen
| EOFTerminated _ => UnmatchedOpen
| CBTerminated vals rest' =>
bind (While (Sequence vals)) (parseHelper rest')
end
| _ => parseHelper rest
end
end.
Have you considered using well-founded recursion? Coq's standard library has a series of useful combinators for defining functions over well-founded relations. Reference 1 shows two techniques (well-founded recursion and a monad) for general recursion.
Other technique that is also very useful in context of Agda, is the so-called Bove-Capretta method, which defines an inductive predicate that mimics the call graph of defined function.
Coq also has the Function command that can be used to define more general recursive functions. Whenever I needed to define non-structurally recursive functions, I have used well-founded recursion.
Hope that this helps you.
Define a function which computes the sum of all the integers in a
given list of lists of integers. No 'if-then-else' or any auxiliary
function.
I'm new to to functional programming and am having trouble with the correct syntax with SML. To begin the problem I tried to create a function using pattern matching that just adds the first two elements of the list. After I got this working, I was going to use recursion to add the rest of the elements. Though, I can't even seem to get this simple function to compile.
fun listAdd [_,[]] = 0
| listAnd [[],_] = 0
| listAnd [[x::xs],[y::ys]] = x + y;
fun listAdd [] = 0
| listAdd ([]::L) = listAdd L
| listAdd ((x::xs)::L) = x + listAdd (xs::L)
should do what it looks like you want.
Also, it looks like part of the problem with your function is that you give the function different names (listAdd and listAnd) in different clauses.
For the sake of simplicity, I'd say you probably want this :
fun listAdd : (int * int) list -> int list
Now, I would simply define this as an abstraction of the unzip function :
fun listAdd ls :
case ls of
[] => 0
| (x,y) :: ls' => (x + y) + (listAdd ls')
I think there is no point in taking two separate lists. Simply take a list that has a product of ints. If you have to build this, you can call the zip function :
fun zip xs ys :
case xs, ys of
[], [] => []
| xs, _ => []
| _, ys => []
| x::xs', y::ys' => (x,y) :: (zip xs' ys')
In general, if you really wanted, you can write a far more abstract function that is of the general type :
fun absProdList : ((`a * `b) -> `c) -> (`a * `b) list -> `c list
This function is simply :
fun absProdList f ls =
case l of
[] => []
| (x,y) :: ls' => (f (x,y)) :: (absProdList f ls')
This function is a supertype of the addList function you mentioned. Simply define an anonymous function to recreate your addList as :
fun addList' ls =
absProdList (fn (x,y) => x + y) ls
As you can see, defining the generic type-functions makes specific calls to functions that are type-substitutions to the general one far easier and much more elegant with the appropriate combination of : Currying, Higher-Order Functions and Anonymous Functions.
You probably don't want an int list list as input, but simply an int list * int list (pair of int lists). Besides this, your function seems to returns numbers rather than a list of numbers. For this you would use recursion.
fun listAdd (x::xs, y::ys) = (x + y) :: listAdd (xs, ys)
| listAdd ([], _) = []
| listAdd (_, []) = [] (* The last two cases can be merged *)
You probably want to read a book on functional programming fron the first page and on. Pick for example Notes on Programming in SML/NJ by Riccardo Pucella if you want a free one.