I've just watched an interview on YouTube with Simon Peyton Jones where they talk about Epic's Verse language. Here (at roughly 51:30) they start talking about the type system.
Simon mentions that Verse's version of type checking (he calls it verification) is done via functions written in Verse. These functions have to be side-effect free and receive one value as an argument. This argument is then checked inside this function of whether it adheres to the spec of the type we want to define and either succeeds with a certain value (the type checks out) or fails (it doesn't type-check).
For example, to define a type even
that only accepts even integers, I could write something along these lines (using Haskell here since I'm not familiar enough with Verse):
int x = True -- pseudo function to check whether a value is an integer
even x | int x && x `mod` 2 == 0 = x
| otherwise = error "doesn't type check"
-- pseudo Haskell
x :: even
x = 1 -- uneven, type error
x = 2 -- even, ok
Now this is a fairly easy example where a compiler could figure this out statically (I guess this is what refinement types are?), but what happens if the compiler cannot see the value of x
(e.g. it's read from stdin at runtime)?
At 53:35 in the interview, Simon then explains some of the benefits of static type checking and how Verse approaches this topic. He then says, that the verifier can either accept or fail a type test, but it (in my opinion) sounds like failing verification doesn't necessarily result in the program being rejected by the compiler (see 55:00). Does this mean that there will be some sort of type checking happening at runtime? Or does he just mean that type checking can fail for rather arbitrary/opaque reasons until the verifier is more fleshed out?
Disclaimer: I'm not an expert in PL design, so I might've gotten some details wrong. I apologize in advance.