notjack
2018-8-9 12:05:51

how come impersonator contracts are “wrong” on immutable struct fields but perfectly acceptable on list elements? what makes an immutable list different from an immutable struct?


mflatt
2018-8-9 12:58:01

@leif I don’t remember for sure, but I think it’s needed to have fonts when the host doesn’t otherwise have any fonts installed.


samth
2018-8-9 14:22:02

@notjack everyone has access to the cons constructor


notjack
2018-8-9 14:25:27

@samth I don’t follow at all


notjack
2018-8-9 14:28:42

thinking through this more - is the important part that a struct/c contract on an instance of the structure type break invariants imposed by the guard procedure of the type?


notjack
2018-8-9 14:35:36

I’m seeing that there exists impersonate-struct, chaperone-struct, and chaperone-struct-type but no impersonate-struct-type which seems related


samth
2018-8-9 14:47:03

Yes that’s right (or just by hiding the constructor)


samth
2018-8-9 14:58:46

if you’re given an immutable structure value with 1 and 2 in the fields, you can’t in general produce a similar struct with 3 and 4 as the field values


samth
2018-8-9 14:58:59

while obviously if you have a pair with 1 and 2, it’s easy to write (cons 3 4)


notjack
2018-8-9 15:29:42

So if I had a geometry library with a (point x y) struct and provided a (point/c x-contract y-contract) combinator that allowed impersonator contracts, somebody could just make an impersonator contract that turns (point 1 2) into (point 'general 'nonsense) and explode my library code that internally uses unsafe math ops on point fields because it assumes they’re always numbers.


samth
2018-8-9 15:30:39

yes


notjack
2018-8-9 15:31:42

if I never allow chaperones / impersonators on specific instances of a struct, is it safe to allow impersonation in the struct type constructor? (ignoring subtyping)


notjack
2018-8-9 15:32:57

concretely this came up a long time ago for me because I wanted an optional / maybe type with an optional/c contract combinator that allowed parametric contracts


notjack
2018-8-9 15:33:19

and I couldn’t figure out how to do that beyond just shrugging and making the field of the internal optional struct mutable


samth
2018-8-9 15:33:37

yes, i think so


notjack
2018-8-9 15:44:52

@samth Related line of inquisition: I noticed that the data/order and data/enumeration libraries actually carry the component contracts around explicitly with the order / enum and give you functions to access them. I’ve taken to doing that for most of my uses of contracts lately, but in a way where the constructors don’t accept contracts and the combinators make contracts that implicitly add the component contracts to the value after chaperoning / impersonating. So I’ll end up with an API that looks something like this:

make-frobnicator : {{some function or whatever}} -> frobnicator?
frobnicator/c : (-> contract? contract?)
frobnicator-domain : (-> frobnicator? contract?)
frobnicate! : (->i ([frob frobnicator?] [v (frob) (frobnicator-domain)]) [_ void?])

I was able to do this a few ways: one, I made my own impersonator properties containing the contracts and stuck them in various places; two, I made separate struct types like chaperone-frobnicator and impersonator-frobnicator that have the extra contracts and work correctly with chaperone-of? and impersonator-of?; and three, I used one frobnicator struct with fields for the contracts that default to no contract and overrode gen:equals+hash to just ignore those contract fields so chaperone-of? and impersonator-of? work automatically. Do any of those approaches sound broken? Does one seem obviously better than the others to you?


samth
2018-8-9 15:46:06

I don’t see anything particular better or worse, but the authors of those libraries (such as @robby or @maxsnew) might have more ideas


robby
2018-8-9 15:49:37

The enumerators use the contracts because the contracts are a handy way to express what the enumerators actually enumerate.


notjack
2018-8-9 15:53:44

The paper on the enumerators library was very helpful


notjack
2018-8-9 15:58:39

Maybe I should write this up in a racket users post with more examples


notjack
2018-8-9 15:59:52

eventually


notjack
2018-8-9 19:06:31

@samth just realized something about the point/c example: what if I placed contracts… on the field contracts? Like, allowed impersonation but enforce that the impersonator contracts always return numbers


samth
2018-8-9 19:06:58

I don’t know if that’s possible for contracts


notjack
2018-8-9 19:08:41

I think it is - probably by making something like (contract/c in out) that wraps a contract with one that checks what it’s used on and what it returns


joergen7
2018-8-9 19:50:07

Hi all,


joergen7
2018-8-9 19:50:41

I’m trying to create a predicate in typed racket to assert types.


joergen7
2018-8-9 19:51:13

Above is the best solution I can come up with but sadly it doesn’t work that way.


lexi.lambda
2018-8-9 19:51:38

Are you familiar with define-predicate?


joergen7
2018-8-9 19:51:49

not yet. Let me google it.


lexi.lambda
2018-8-9 19:52:18

Don’t use google, use the Racket docs search: http://docs.racket-lang.org/search/index.html?q=define-predicate


joergen7
2018-8-9 19:52:26

thanks


joergen7
2018-8-9 19:55:06

joergen7
2018-8-9 19:55:34

As I understand the docs I should be able to do something like this but … no way.


lexi.lambda
2018-8-9 19:56:07

You need (define-predicate list-of-string? (Listof String)); the grammar in the docs is (define-predicate name t).


joergen7
2018-8-9 19:56:22

forgot the name! works!


joergen7
2018-8-9 19:56:37

sry was confused by make-predicate


joergen7
2018-8-9 19:56:55

awesome, that was zero work


joergen7
2018-8-9 19:57:21

let’s see if it works for my super-duper data-structures…


joergen7
2018-8-9 20:00:59

Type Checker: Type Selectivity-Data could not be converted to a predicate: required a flat contract but generated a chaperone contract in: Selectivity-Data


lexi.lambda
2018-8-9 20:01:23

what is Selectivity-Data?


joergen7
2018-8-9 20:01:59

joergen7
2018-8-9 20:02:17

sry for spamming you with code and error messages


lexi.lambda
2018-8-9 20:02:55

hashes and vectors can be mutable, so, for example, even if a hash contains only string keys and list values when you test a predicate, it might be modified by another thread


joergen7
2018-8-9 20:03:14

so I need an immutable hash instead?


lexi.lambda
2018-8-9 20:03:17

and that other thread might insert a non-string key or a non-list value. so TR refuses to accept the predicate.


lexi.lambda
2018-8-9 20:03:36

I think there are immutable hash types in TR now, but I don’t think there are immutable vector types. I could be wrong, though.


joergen7
2018-8-9 20:04:09

Maybe I can work around it by making the vector something else.


joergen7
2018-8-9 20:04:29

So the hash needs to be immutable and the vector needs to go away, maybe I can do that.


lexi.lambda
2018-8-9 20:04:50

if you are just using the vector to store pairs, lists or cons pairs should be fine, which are immutable.


joergen7
2018-8-9 20:04:55

there are immutable hashtables btw


lexi.lambda
2018-8-9 20:05:22

it should work if you change the type to (Immutable-HashTable String (Listof (List Real Real))).


joergen7
2018-8-9 20:05:25

it depends on what plot wants. but I think I remember, it expects only a sequence there


joergen7
2018-8-9 20:05:46

that’s what I’ll try, thanks for the hint in any case.


joergen7
2018-8-9 20:06:28

the (Listof (Vector Real Real)) goes into points eventually.


lexi.lambda
2018-8-9 20:06:49

a workaround for this in general is to use a struct instead of a type alias. so if you do (struct selectivity-data ([value : (HashTable String (Listof (Vector Real Real)))])) then use selectivity-data?, then TR will treat that as sufficient evidence that selectivity-data-value will produce the type you want.


joergen7
2018-8-9 20:08:01

really? how does it make a difference to wrap it in a struct?


lexi.lambda
2018-8-9 20:08:34

this is because constructing a selectivity-data structure imposes a requirement on the caller that the value has a sufficiently restrictive type, so the predicate selectivity-data? only needs to check the tag (the wrapper struct) to know the guarantee was met, rather than inspect the data inside.


joergen7
2018-8-9 20:09:17

interesting


lexi.lambda
2018-8-9 20:09:21

when you use the value in typed code, the type system will ensure you can’t break the guarantee, and if the data crosses a typed/untyped boundary, TR will wrap it in a contract that ensures the guarantee will hold.


joergen7
2018-8-9 20:10:12

that is useful to know, some day I might not be able to work around mutable hash-tables and vectors.


joergen7
2018-8-9 20:10:52

as always, you are a big help! thank you so much.