How to use typed scheme/racket - scheme

I am trying to learn typed scheme/racket(?). Down below I have an example from my code:
#lang typed/racket
(: add (Real Real -> Real))
(define (add x y)
(+ x y))
I would like to implement a procedure "check" which checks if two datatypes are allowed with an operator. For example,
(check '(+ int int))
Should result in
int
But
(check '(* int (+ real int)))
Should result in something like this:
The operator '+' must have two operands of the same (numerical) type.
That is, check should take a list.
Questions:
How do I implement "check"? Firstly I though "ok, I have a list, so let's use car and cdr" to get the operator and the operands but it didn't work and I don't even know why it doesn't work. I also though about making if statements like (if (and (= x y) (or (= x int) (= y int)) and so on to make the checks but... don't think this is the right way to go.
Should I make a procedure "add" or not? Is there any other way to do this? Int the examples it looks like they are only using "+", "-" and so on. Lastly; How do I check that the input "int" is an int and then gives int as output.
I am pretty lost right now and I am sorry for my pretty vaugue questions but I would be really happy if someone could help me out to understand this.
Note: the procedure add takes real numbers and output a real number so it doesn't follow along with the example too well. But I hope you grasp the idea. Thanks :)

You're asking a fascinating question, and it doesn't have a simple answer.
The program that you're trying to write is essentially a type-checker. That is, it takes an expression, and checks to see whether the given function's domain includes the arguments it's being called with. We can write one of those, but I suspect you're going to be unsatisfied. Here, let me go write one now....
#lang typed/racket
(require typed/rackunit)
;; a type is either
;; - 'number, or
;; - (list 'fn list-of-types type)
;; examples of types
'number
'(fn (number number) number)
(define-type FnTy (List 'fn (Listof Ty) Ty))
(define-type Ty (U 'number FnTy))
;; given an expression, returns a type
;; or signals an error
(: check (Any -> Ty))
(define (check input)
(cond [(and (list? input)
(pair? input)
(symbol? (car input)))
(define fn-ty (lookup-fn-type (car input)))
(define arg-types (map check (rest input)))
(cond [(equal? (cadr fn-ty) arg-types)
(caddr fn-ty)]
[else (error 'check
"expression didn't type-check: ~v\n"
input)])]
[(number? input)
'number]
[else (raise-argument-error
'check
"well-formed expression"
0 input)]))
(: lookup-fn-type (Symbol -> FnTy))
(define (lookup-fn-type fn-name)
(match fn-name
['+ '(fn (number number) number)]
[other (raise-argument-error 'lookup-fn-type
"known function name"
0 fn-name)]))
(define TEST-INPUT '(+ 3 43))
(check-equal? (check TEST-INPUT)
'number)
(check-equal? (check '(+ (+ 3 4) 129837))
'number)
Does this answer any part of your question?

Related

Maximum recursion error [duplicate]

I'm reading The Little Schemer. And thanks to my broken English, I was confused by this paragraph:
(cond ... ) also has the property of not considering all of its
arguments. Because of this property, however, neither (and ... ) nor
(or ... ) can be defined as functions in terms of (cond ... ), though
both (and ... ) and (or ... ) can be expressed as abbreviations of
(cond ... )-expressions:
(and a b) = (cond (a b) (else #f)
and
(or a b) = (cond (a #t) (else (b))
If I understand it correctly, it says (and ...) and (or ...) can be replaced by a (cond ...) expression, but cannot be defined as a function that contains (cond ...). Why is it so? Does it have anything to do with the variant arguments? Thanks.
p.s. I did some searching but only found that (cond ...) ignores the expressions when one of its conditions evaluate to #f.
Imagine you wrote if as a function/procedure rather than a user defined macro/syntax:
;; makes if in terms of cond
(define (my-if predicate consequent alternative)
(cond (predicate consequent)
(else alternative)))
;; example that works
(define (atom? x)
(my-if (not (pair? x))
#t
#f))
;; example that won't work
;; peano arithemtic
(define (add a b)
(my-if (zero? a)
b
(add (- a 1) (+ b 1))))
The problem with my-if is that as a procedure every argument gets evaluated before the procedure body gets executed. thus in atom? the parts (not (pair? x)), #t and #f were evaluated before the body of my-if gets executed.
For the last example means (add (- a 1) (+ b 1)) gets evaluated regardless of what a is, even when a is zero, so the procedure will never end.
You can make your own if with syntax:
(define-syntax my-if
(syntax-rules ()
((my-if predicate consequent alternative)
(cond (predicate consequent)
(else alternative)))))
Now, how you read this is the first part is a template where the predicate consequent and alternative represent unevaluated expressions. It's replaced with the other just reusing the expressions so that:
(my-if (check-something) (display 10) (display 20))
would be replaced with this:
(cond ((check-something) (display 10))
(else (display 20)))
With the procedure version of my-if both 10 and 20 would have been printed. This is how and and or is implemented as well.
You cannot define cond or and or or or if as functions because functions evaluate all their arguments. (You could define some of them as macros).
Read also the famous SICP and Lisp In Small Pieces (original in French).

DrRacket define begin set! probably should work but dont

Im learning for exam of programming in lisp using DrRacket..
In presentation from lectures i found this code:
(define (f a b c)
(define delta)
(begin
(set! delta (- (* b b) (* 4 a c))
(if (>=? delta 0)
(writeln ”są pierwiastki”)
(writeln ”nie ma pierwiastków)))))
But it dont work.
DrRacket is showing:
. define: bad syntax (missing expression after identifier) in: (define delta)
Can't I set delta value later?
What is the problem?
thanks in advance
The original error message is because
(define delta)
is missing a value. Instead it should be something like:
(define delta 0)
There some other issues:
The double quotes weren't the " character and weren't recognized
by Racket.
Some parens were wrong.
Also I don't know why it was define-ing delta, then immediately
set!-ing it.
I tried to fix/simplify what you posted, and came up with the
following. But I'm not really sure what the function is supposed to
do, so I don't know if the example output is correct.
#lang racket
(define (f a b c)
(define delta (- (* b b) (* 4 a c)))
(if (>= delta 0)
(displayln "są pierwiastki")
(displayln "nie ma pierwiastków")))
;; Example output:
(f 1 2 3)
;;-> nie ma pierwiastków
(f 1 200 3)
;;-> są pierwiastki
Try this:
#lang racket
(define (f a b c)
(define delta 0)
(set! delta (- (* b b) (* 4 a c)))
(if (>= delta 0)
(displayln "są pierwiastki")
(displayln "nie ma pierwiastków")))
What was wrong with your code:
It's probably a copy-paste error, but in Scheme we delimit strings using the " character, not ” as in your code. And the last line is missing the closing ".
Although some interpreters accept a define without an initial value, the standard is that a value must be present after the variable name
A closing parenthesis is missing at the end of the set! line
The define and set! lines can be merged into a single line: (define delta (- (* b b) (* 4 a c)))
The >=? operator is not standard in Scheme, it might work in your interpreter but if possible use the standard >=
The writeln procedure is not standard in Scheme, in Racket you can substitute it for displayln
Not really an error, but you don't need to write a begin inside a procedure definition, it's implicit
In conclusion: the code in the question seems to be intended for a different interpreter, this question was tagged racket but believe me, what you have is not valid Racket code - heck, is not even standard Scheme. Make sure to use the correct interpreter, and be very alert for typos in the text.
I think Greg already has a perfect answer to your problem, but I just want to add the obvious let version of his code as well:
;; for a given ax^2+bx+c=0
;; this displays if it has at least one
;; real number answer or not
(define (equation-has-answer a b c)
(let ((delta (- (* b b) (* 4 a c))))
(if (>= delta 0)
(displayln "Has answer(s)")
(displayln "Has no answers"))))
To just make a predicate you can do this:
;; for a given ax^2+bx+c=0
;; this returns #t if it has at least one
;; real number answer and #f otherwise
(define (equation-has-answer? a b c)
(>= (- (* b b) (* 4 a c)) 0))

How can I unsplice a list of expression into code?

I have an experiment for my project, basically, I need to embedded some s-expression into the code and make it run, like this,
(define (test lst)
(define num 1)
(define l (list))
`#lst) ; oh, this is not the right way to go.
(define lst
`( (define num2 (add1 num))
(displayln num2)))
I want the test function be like after test(lst) in racket code:
(define (test lst)
(define num 1)
(define l (list))
(define num2 (add1 num)
(displayln num2))
How can I do this in racket?
Update
The reason I would like to use eval or the previous questions is that I am using Z3 racket binding, I need to generate formulas (which uses racket binding APIs), and then I will fire the query at some point, that's when I need to evaluate those code.
I have not figured out other ways to go in my case...
One super simple example is, imagine
(let ([arr (array-alloc 10)])
(array-set! arr 3 4))
I have some model to analyze the constructs (so I am not using racketZ3 directly), during each analyzing point, I will map the data types in the program into the Z3 types, and made some assertions,
I will generate something like:
At allocation site, I will need to make the following formula:
(smt:declare-fun arr_z3 () IntList)
(define len (make-length 10))
Then at the array set site, I will have the following assertions and to check whether the 3 is less then the length
(smt:assert (</s 3 (len arr_z3)))
(smt:check-sat)
Then finally, I will gather the formulas generated as above, and wrap them in the form which is able to fire Z3 binding to run the following gathered information as code:
(smt:with-context
(smt:new-context)
(define len (make-length 10))
(smt:assert (</s 3 (len arr_z3)))
(smt:check-sat))
This is the super simple example I can think of... making sense?
side note. Z3 Racket binding will crash for some reason on version 5.3.1, but it mostly can work on version 5.2.1
Honestly, I don’t understand what exactly you would like to achieve. To quote N. Holm, Sketchy Scheme, 4.5th edition, p. 108: »The major purpose of quasiquotation is the construction of fixed list structures that contain only a few variable parts«. I don’t think that quasiquotation would be used in a context like you are aiming at.
For a typical context of quasiquotation consider the following example:
(define (square x)
(* x x))
(define sentence
'(The square of))
(define (quasiquotes-unquotes-splicing x)
`(,#sentence ,x is ,(square x)))
(quasiquotes-unquotes-splicing 2)
===> (The square of 2 is 4)
Warning: if you're not familiar with how functions work in Scheme, ignore the answer! Macros are an advanced technique, and you need to understand functions first.
It sounds like you're asking about macros. Here's some code that defines test to be a function that prints 2:
(define-syntax-rule (show-one-more-than num)
(begin
(define num2 (add1 num))
(displayln num2)))
(define (test)
(define num1 1)
(show-one-more-than num1))
Now, I could (and should!) have written show-one-more-than as a function instead of a macro (the code will still work if you change define-syntax-rule to define), but macros do in fact operate by producing code at their call sites. So the above code expands to:
(define (test)
(define num1 1)
(begin
(define num2 (add1 num1))
(displayln num2)))
Without knowing the problem better, it's hard to say what the correct approach to this problem is. A brute force approach, such as the following:
#lang racket
(define (make-test-body lst)
(define source `(define (test)
(define num 1)
(define l (list))
,#lst))
source)
(define lst
`((define num2 (add1 num))
(displayln num2)))
(define test-source
(make-test-body lst))
(define test
(parameterize ([current-namespace (make-base-namespace)])
(eval `(let ()
,test-source
test))))
(test)
may be what you want, but probably not.

Finite State Machine in Scheme

I am trying to finish a finite state machine in Scheme. The problem is, that I am not sure how to tell it what characters it should test. If I want to test a String "abc112" then how do I do that?
Here is the code:
#lang racket
(define (chartest ch)
(lambda (x) (char=? x ch)))
;; A transition is (list state char!boolean state)
(define fsmtrlst
(list
(list 'start char-alphabetic? 'name)
(list 'start char-numeric? 'number)
(list 'start (chartest #\() 'lparen)
(list 'start (chartest #\)) 'rparen)
(list 'name char-alphabetic? 'name)
(list 'name char-numeric? 'name)
(list 'number char-numeric? 'number)))
(define (find-next-state state ch trl)
(cond
[(empty? trl) false]
[(and (symbol=? state (first (first trl)))
((second (first trl)) ch))
(third (first trl))]
[else (find-next-state state ch (rest trl))]))
(define fsmfinal '(name number lparen rparen))
(define (run-fsm start trl final input)
(cond
[(empty? input)
(cond
[(member start final) true]
[else false])]
[else
(local ((define next (find-next-state start (first input) trl)))
(cond
[(boolean? next) false]
[else (run-fsm next trl final (rest input))]))]))
And here is the launch code which I am trying to test:
(fsmtrlst (list 'start (lambda (abc112) (char=? abc112 ))))
EDIT:
ok,.. the overall product is okey, but my tutor is not happy with it,.. he wants me to make a finite state machine with transition function -> something like a global definition which would say: when in state X comes character Y go to Z ... and then i will test a list of characters to see if it is false or true ... So the only difference is that the code shouldn't be specific to use only numbers and letters but any character... is it somehow possible? thank you for your answer
EDIT 2: now I have the basic info how it should look like:
That is, the machine looks like
A ---------> B ----------> C ----------> D ----------> (E)
letter number number letter
(define fsmtrlst
(list
(list 'A char-alphabetic? 'B)
(list 'B char-numeric? 'C)
(list 'C char-numeric? 'D)
(list 'D char-alphabetic 'E)))
(define fsmfinal '(E))
(define fsmstart 'A)
but i am not sure how to write the definition of fsmstart.
Thank you for answers.
This accepts sequences of exactly four characters which are letter, number, number, letter, and nothing else.
EDIT 3: I am using tutorials online and a book that my mentor teacher provided. I figured out the fsm I wanted to make. Thank you for your help.
Just out of curiosity:
How would differ to have rather specific fsm?
Example:
START ----"b"-----> STATE A -----"a" ----> STATE B -----"c"-----> FINAL STATE
That the fsm would be true only when the list of characters is "bac" and nothing else.
Is it possible?
Thank you for your feedback.
EDIT 4:
Ok, I managed to do write but once again, I am not sure how to make the input of characters. This is the code:
There are 3 states but it will be true only when going from state A to state C.
(define (chartest ch)
(lambda (x) (char=? x ch)))
(define fsm-trans
'((A, "a", B), (A, "b", A), (B, "c", C)))
(define (find-next-state state ch trl)
(cond
[(empty? trl) false]
[(and (symbol=? state (first (first trl)))
((second (first trl)) ch)) <- And also this line returns an error
(third (first trl))]
[else (find-next-state state ch (rest trl))]))
(define fsm-final '(C))
(define start-state 'A)
(define (run-fsm start trl final input)
(cond
[(empty? input)
(cond
[(member start final) true]
[else false])]
[else
(local ((define next (find-next-state start (first input) trl)))
(cond
[(boolean? next) false]
[else (run-fsm next trl final (rest input))]))]))
(run-fsm start-state fsm-trans fsm-final (list '("a", "c"))) <- I know this is the last problem with the code, the definition of the input. How can I tell Scheme what characters I want to test?
Thank you for your answer!!!
I am curious: I take it you did not write this fsm? Is this for a homework assignment or are you trying to teach yourself? The code for the FSM looks fine (quite fine, in fact). However, your launch line:
(fsmtrlst (list 'start (lambda (abc112) (char=? abc112 ))))
Makes no sense. Here is why: fsmtrlst is the finite state machine transition list. It was defined in the first big block of code. It is not a function to be called. I believe the function you want to call is run-fsm. That takes a start symbol, a transition list, a list of final states, and an input. The input is not actually a string, but a list. As a consequence, you can launch it with the following line:
(run-fsm 'start fsmtrlst fsmfinal (string->list "abc112"))
That will call run-fsm with the defined transition list fsmtrlst, the defined list of final states, and the input-ready form of the string "abc112".
Incidentally, everything except 'start is defined to be a final (accepting) state. Not all inputs are accepting inputs, though. For example, replacing "abc122" with "abc(122" is not accepted.
Is this what you want?
Update:
Your edit has clarified things. Your definition of fsmstart is fine. You did miss a question mark (?) on one of your char-alphabetic? usages in fsmtrlst. Is your confusion that you don't know how to use your new definitions? First, you should remove the old definitions of fsmtrlst and fsmfinal. Otherwise, you will likely get a duplicate definition error. From your new definition, your line to execute should look like:
(run-fsm fsmstart fsmtrlst fsmfinal (string->list "w00t"))
This will return #t, because "w00t" is a character followed by two numbers, followed by a character.
I speculate that you are still having difficulty with the syntax rules of scheme, and not just problems with the logic of your particular program. You might want to try a simpler exercise.
UPDATE 2: Shouldn't you consider formulating a new question?
Your most recent update has broken the code. The transition portion of the fsm worked because transitions were defined as a list:
(from-state test-function to-state)
You have attempted to create a transition:
(from-state string-literal to-state)
You could change (A, "a", B) to (A (lambda (x) (string=? x "a") B).
When you tried to invoke your function, you took a function that expected a list of characters and gave it a list of list of strings. These are not the same thing. Also, did you notice that you put commas in your lists, but they existed nowhere else in the code? These mistakes are why I suggest you begin a scheme tutorial. These are basic scheme problems, unrelated to your particular exercise. I suggest you rewind your edits to what you had yesterday.
Unfortunately, I can no longer update this answer. I wanted to update my answer so that if someone came along your question with similar concerns, they would see a complete answer. However, you have provided a moving target. Please consider halting your edits and submit a new question when you have one.

double in scheme

How to write a program in scheme that takes an arbitrary
sexpression consisting of integers and which returns an sexpression that is identical to
the original but with all the integers doubled?
We want a procedure that takes an S-expression as input, and outputs an S-expression with the same structure, but where each integer is doubled; generally, a procedure to map S-expressions:
(define (double x)
(if (number? x)
(* x 2)
x)))
(define (sexp-map op sexp)
...)
(sexp-map double some-sexpression)
The S-expression we get (SEXP) is going to be either an atom, in which case the result is (OP SEXP), or a list of S-expressions. We might think to map OP across SEXP in this case, but S-expressions nest arbitrarily deep. What we should actually do is map a procedure that will transform each element in the smaller S-expression with OP. Well would you look at that, that's just another way to describe of the goal of the procedure we're currently trying to write. So we can map SEXP-MAP across SEXP.
Well, no we can't actually, because SEXP-MAP needs to be called with two arguments, and MAP will only give it the one. To get around that, we use a helper procedure F of one argument:
(define (sexp-map op sexp)
(define (f x)
(if (list? x)
(map f x)
(op x)))
(f sexp))
F winds up doing all the real work. SEXP-MAP is reduced to being a facade that's easier to use for the programmer.
It sounds like what you want is to find each integer in the s-expression, then double it, while keeping the rest of it the same.
If you're not aware, s-expressions are just lists that may happen to contain other lists, and it makes sense to deal with them in levels. For instance, here's a way to print all the values on level one of an s-expression:
(define (print-level-one sexp)
(display (car sexp))
(print-level-one (cdr sexp)))
This will end up calling display on the car of every part of the s-expression.
You could do something similar. You'll need the functions integer? and pair? to check whether something is an integer, which should be doubled, or another list, which should be treated just like the top-level list.
(Note: I'm being deliberately vague because of the comment about homework above. If you just want the answer, rather than help figuring out the answer, say so and I'll change this.)
An Sexp of numbers is one of
-- Number
-- ListOfSexp
A ListOfSexp is one of
-- empty
-- (cons Sexp ListOfSexp)
So, you'll need one function to handle both of those data definitions. Since the data definitions cross-reference each other, the functions will do the same. Each individual function is pretty straight forward.
(define (double E)
(cond ((null? E) '())
((list? (car E)) (cons (double (car E)) (double (cdr E))))
((number? E) (list E))
(else (cons (* 2 (car E)) (double (cdr E))))
))
(map (lambda (x) (* x 2)) '(1 2 3 4 5)) => '(2 4 6 8 10)
What does it do? (lambda (x) (* x 2)) takes a number and doubles it, and map applies that function to every element of a list.
Edit: Oh, but it won't go into trees.
(define double
(lambda (x)
(cond ((null? x) (list))
((list? (car x)) (cons (double (car x)) (double (cdr x))))
(else (cons (* 2 (car x)) (double (cdr x)))))))
EDIT
Fixed this. Thanks to Nathan Sanders for pointing out my initial oversight concerning nested lists.

Resources