pihentagy
2021-1-4 08:27:54

@pihentagy has joined the channel


oldsin
2021-1-4 10:07:51

@oldsin has joined the channel


pihentagy
2021-1-4 12:48:57

Having a file with integers in each line (advent of code, day 1), how can I make this lines typed/racket safe?


pihentagy
2021-1-4 12:51:00

I guess I should somehow filter out non-integer lines, but this does not help:


pihentagy
2021-1-4 12:51:21

Type Checker: Polymorphic function `filter' could not be applied to arguments: Types: (-> a Any) (Listof a) -> (Listof a) Arguments: (-> Any Boolean) (Listof (U Complex False)) Expected result: (-> (Listof Integer)) in: (filter integer? (map string->number (file->lines "input1")))


soegaard2
2021-1-4 12:53:00

Try defining a line->number that returns 0 instead of #f. Then use that with map.


pihentagy
2021-1-4 13:16:39

I don’t get it.


laurent.orseau
2021-1-4 13:25:15

what @soegaard2 is saying is that string->number can return #f instead of a number


laurent.orseau
2021-1-4 13:26:13

So lines can be a list of numbers or #f


sorawee
2021-1-4 13:26:46

But he filters it with integer?, so he expects it to work


sorawee
2021-1-4 13:26:52

In fact, it almost works!


sorawee
2021-1-4 13:27:26

There are two problems


sorawee
2021-1-4 13:27:42

First, the type annotation should be (: lines (Listof Integer))


sorawee
2021-1-4 13:27:56

This is because lines is a list of integers, not a function that produces a list of integers


sorawee
2021-1-4 13:28:09

Second, you need to use exact-integer? instead of integer?


sorawee
2021-1-4 13:28:27

This is because (integer? 1.0) returns #t


sorawee
2021-1-4 13:28:34

But 1.0 does not satisfy Integer


sorawee
2021-1-4 13:29:02

Here’s the full code


sorawee
2021-1-4 13:29:03

#lang typed/racket (: lines (Listof Integer)) (define lines (filter exact-integer? (map string->number (file->lines "input1"))))


sorawee
2021-1-4 13:31:20

I think this is the case where the type error message is not ideal


pihentagy
2021-1-4 13:31:34

I am surprized why it works. It needs to peek inside the function argument of filter to allow that :open_mouth:


gknauth
2021-1-4 13:31:50

In the Scala world, people use flatMap instead of map when you might have non-values sprinkled in with values in the input. If you have List(Some(2), None, None, Some(4), None, Some(6), None), and you flatMap over it, it ignores the Nones and pulls out 2, 4, 6 and operates on those. @sorawee’s comment above is fine, though.


sorawee
2021-1-4 13:32:32

@pihentagy can you elaborate more on your surprise? Why is it surprising?


pihentagy
2021-1-4 13:32:50

And also disappointed that Integer and integer? is not in pair


sorawee
2021-1-4 13:33:31

Yeah, I believe it’s that way to maintain backward compatibility


pihentagy
2021-1-4 13:33:53

Because string->number has a result type of (U Complex False)


sorawee
2021-1-4 13:34:35

Right. Typed Racket has a sophisticated type system that supports the “occurrence typing” feature


pihentagy
2021-1-4 13:34:38

and this time filter narrows the type



soegaard2
2021-1-4 13:35:34

pihentagy
2021-1-4 13:36:32

My type definition of lines is wrong and noone has noticed. lines is not a function


laurent.orseau
2021-1-4 13:36:56

@pihentagy :wink:


pihentagy
2021-1-4 13:37:35

And I missed to notice my statement was false :slightly_smiling_face:


pihentagy
2021-1-4 13:37:47

oooh, my bad


pihentagy
2021-1-4 13:37:59

I failed at reading


gknauth
2021-1-4 14:03:51

@soegaard2 Thanks, hadn’t seen that diagram before, or maybe I forgot. Very helpful.


laurent.orseau
2021-1-4 18:01:10

capfredf
2021-1-4 19:25:15

filter-map should work for this case


anything
2021-1-4 19:25:48

(define (one-round g) [...] [(symbol=? winner 'TIE) (one-round (error "blow!") (make-game (list A B) new-table (add1 (game-round g))))])) I was at the GNU Emacs REPL (Emacs 27.1, Hendershott’s racket-mode) and I typed (require errortrace). Then I said (watch-game (new-game 2 2)). The output made perfect sense to me: ; blow! ; errortrace...: ; draft.rkt::79914: (error "blow!") ; draft.rkt::79903: (one-round (error "blow!") (make-game (list A B) new-table (add1 (game-round ....)))) ; draft.rkt::80003: (watch-game (new-game 2 2)) Then I added (require errortrace) to my draft.rkt and reloaded the REPL DrRacket-style. Now when I do the same thing, I get: ; blow! ; errortrace...: ; draft.rkt::80163: (watch-game (new-game 2 2)) It’s different. I removed (require errortrace) from draft.rkt and reloaded the REPL. Then I said (require errortrace) at the REPL and invoked (watch-game …) again and I got very similar output as the previous. So I can’t seem to reproduce that three-line errortrace that I produced first. I’m puzzled. Why did I see that first stack trace and don’t see it again?

Why does the second output makes less sense to me than the first? It’s not showing the call to (one-round …).


ben.knoble
2021-1-4 19:40:59

Right—in a world like ML/Haskell, this would not be possible. You’d have a sum-type (e.g., type line = number option) and you could use something like filter Option.isSome o map Int.fromString to keep only the valid lines; but the type would always be line list === number option list . You would have to use List.mapPartial (à la flat-map) to get number list . We can prove that all the options are SOMEs, but the type-system cannot. AFAICT, typed-racket can distinguish the cases…


greg
2021-1-4 19:52:00

I’m not sure why. If you want to open an issue at https://github.com/greghendershott/racket-mode/issues and include a code example I can try, I’d be happy to take a look.


greg
2021-1-4 19:52:09

But also…


greg
2021-1-4 19:52:36

Racket Mode has that kind of errortrace “built in”. https://www.racket-mode.com/#racket_002derror_002dcontext


greg
2021-1-4 19:52:53

So if that meets your need, great.


greg
2021-1-4 19:53:33

Of course it’s possible that Racket Mode’s use of errortrace-lib is somehow conflicting with your use of it directly. And if so, that may be an issue that I need to address. idk.


greg
2021-1-4 19:54:00

But practically it might be moot if using racket-error-context set to 'high is all you need, for what you’re doing.


greg
2021-1-4 19:54:18

@anything ^


greg
2021-1-4 19:57:02

And/or, I think maybe you’re doing the thing it says not to do, here? :) https://docs.racket-lang.org/errortrace/using-errortrace.html


greg
2021-1-4 19:57:57

How I would explain it (someone can correct me) is that errortrace takes a program, fully expands it, and rewrites as a somewhat different program.


greg
2021-1-4 19:58:18

It can take your program, and rewrite it as one capable of giving better “stack traces”.


greg
2021-1-4 19:58:38

It can be used to do things like instrumenting your program for profiling.


greg
2021-1-4 19:58:40

And so on.


greg
2021-1-4 19:59:33

But your program rewriting itself using errortrace is generally not possible; it’s something that needs to be done to your program, as part of loading and evaluating your program. Which Racket Mode can do, or the instructions at that doc page show another way to do.


greg
2021-1-4 19:59:42

Hopefully I’m explaining this well.


greg
2021-1-4 20:01:02

As to why it worked, once, from the REPL? The REPL is kind of magical. Sometimes the magic is good and sometimes evil. :slightly_smiling_face:


greg
2021-1-4 20:02:43

Racketeers like to say, “the top-level is hopeless”. Sometimes it raises false hope that something will work in a non-REPL setting.


greg
2021-1-4 20:03:01

The hoplessness and the false hope are two sides of the same coin, I guess.


anything
2021-1-4 20:04:07

I do understand it vaguely — thanks!! (About rewriting my program to be able to provide stack traces.) That makes sense. I must load it before the program is loaded, otherwise the program can’t be rewritten. (I will look into your racket-mode pointers above. Thanks so much. I’ll report anything of relevance later.) Thank you so much.


anything
2021-1-5 00:25:09

You’re right, racket-error-context set to ’high is all I really need. Perfect! Thanks again!


scottclark11
2021-1-5 03:26:03

@scottclark11 has joined the channel


scottclark11
2021-1-5 03:27:09

@scottclark11 has left the channel