[swift-evolution] [Pitch] Constrains for numeric types: Int<1...10> Double<0.0...1.0>

Matthew Johnson matthew at anandabits.com
Wed May 18 09:06:04 CDT 2016


By the way, there is a pretty clever library that allows you to approximate this in Swift today.  It's more verbose than first class language support would be, but not bad given the lack of language support.

https://github.com/Ben-G/Validated


Sent from my iPad

> On May 18, 2016, at 7:49 AM, Adrian Zubarev via swift-evolution <swift-evolution at swift.org> wrote:
> 
> As you guys brought my idea back to life and I’ve done some effort of digging into the Swifts generic future I can show you some fresh ideas.
> 
> `Refinement Types` could be really handy, but put them aside for a moment.
> 
> Actually we could achieve something like Int<minValue, maxValue> in Swift 3. Take a look at this section here: https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#generic-value-parameters
> 
> There is a slightly problem with this, we cannot rewrite all types to be generic with default parameters. That said it would be nice if we could overload types somehow (Int vs. Int<Range>), but I’m not sure if this idea would suit the language like this.
> 
> Anyways we could then have:
> 
> struct Int<_ range: Range<Int>> { … }
> 
> Sadly this makes the type not safe at compile time but only signals the user that at runtime you can’t use any number our of its range.
> 
> -- 
> Adrian Zubarev
> Sent with Airmail
> 
> Am 18. Mai 2016 bei 14:13:09, Vladimir.S via swift-evolution (swift-evolution at swift.org) schrieb:
> 
>> > I generally think it’s a cool idea and that it can be useful in minimizing
>> > partial functions by requiring that these cases are explicitly handled.
>> 
>> Support this opinion.
>> 
>> Other example where such feature could be useful: some public property in 
>> type that can accept values from some interval. For example we have class 
>> with transparency property that can be 0.0 ... 0.1:
>> 
>> class MyShape {
>> public var transparency: Double = 1.0 // 0.0 ... 0.1
>> }
>> 
>> yes, we can use willSet/didSet to check this every time. But if we have a 
>> number of such properties, we have a lot of repetitive and boilerplate code:
>> 
>> class C {
>> var transparancy : Double = 1.0 {
>> didSet { check(transparancy, 0.0...1.0) }
>> }
>> 
>> var prop1 : Int = 1 {
>> didSet { check(prop1, from: -10...10) }
>> }
>> 
>> var prop2 : Int = 1 {
>> didSet { check(prop2, from: 0...100) }
>> }
>> }
>> 
>> , and all will be worse if we also need didSet observers to do some 
>> 'useful' work here.
>> Proposed solution will looks like:
>> 
>> class C {
>> var transparancy : Double<0.0...1.0> = 1.0
>> 
>> var prop1 : Int<-10...10> = 1
>> 
>> var prop2 : Int<0...100> = 1
>> }
>> 
>> Probably the alternative could be some kind of `where` or `bounded` clause 
>> for numeric types and arguments:
>> 
>> class C {
>> var transparancy : Double = 1.0 where 0.0...1.0
>> //var transparancy : Double bounded 0.0...1.0 = 1.0
>> 
>> var prop1 : Int = 1 where -10...10
>> 
>> var prop2 : Int = 1 where 0.0...1.0
>> 
>> //var prop3 : Float bounded 0.0..<100.0 = 0.0
>> }
>> 
>> 
>> On 18.05.2016 11:30, David Rönnqvist via swift-evolution wrote:
>> > It reminds me of "Refinement Types" (see for example [this blog post][1] or
>> > [this paper][2]).
>> >
>> > I generally think it’s a cool idea and that it can be useful in minimizing
>> > partial functions by requiring that these cases are explicitly handled.
>> > For example, highlighting that the following `average` implementation
>> > divides by zero when the list is empty:
>> >
>> > func average(numbers: [Int]) -> Int {
>> > return sum(numbers) / numbers.count
>> > }
>> >
>> >
>> > and requiring that the empty list case is handled separately:
>> >
>> > func average(numbers: [Int]) -> Int {
>> > guard !numbers.isEmpty else { return 0 }
>> > return sum(numbers) / numbers.count
>> > }
>> >
>> >
>> > Regards,
>> > David
>> >
>> > [1]: http://goto.ucsd.edu/~rjhala/liquid/haskell/blog/blog/2013/01/01/refinement-types-101.lhs/
>> > <http://goto.ucsd.edu/%7Erjhala/liquid/haskell/blog/blog/2013/01/01/refinement-types-101.lhs/>
>> > [2]: http://goto.ucsd.edu/~nvazou/refinement_types_for_haskell.pdf
>> > <http://goto.ucsd.edu/%7Envazou/refinement_types_for_haskell.pdf>
>> >
>> >
>> >> On 11 May 2016, at 20:00, Adrian Zubarev via swift-evolution
>> >> <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> >>
>> >> Okay I’m fine with that for now. If you’d have to decide on some syntax
>> >> for such a future, how would it look like? I’m just curious.
>> >>
>> >> I tend to square brackets Double[0.0 … 1.0], because otherwise it might
>> >> look like a generic type, but I’m not sure if this type refinement could
>> >> be applied to other types as well so we actually would stick to the
>> >> generic type syntax here Float<-1.0 … 1.0>.
>> >>
>> >> --
>> >> Adrian Zubarev
>> >> Sent with Airmail
>> >>
>> >> Am 11. Mai 2016 bei 19:54:09, Matthew Johnson (matthew at anandabits.com
>> >> <mailto:matthew at anandabits.com>) schrieb:
>> >>
>> >>> This is called a refinement type. It would be cool to explore that
>> >>> direction in the future but it is definitely well out of scope for Swift 3.
>> >>>
>> >>> Sent from my iPad
>> >>>
>> >>> On May 11, 2016, at 12:45 PM, Adrian Zubarev via swift-evolution
>> >>> <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> >>>
>> >>>> Hello Swift community. I'd like to discuss with you if we need
>> >>>> something like this in Swift 3 or any future Swift version.
>> >>>>
>> >>>> As you may know there is no way to constrain a numeric type expect for
>> >>>> some scope internal assertion or precodintions which may produce a
>> >>>> runtime error if the input value is out of the defined bound.
>> >>>>
>> >>>> func foo(value: Int) {
>> >>>> assert(value > 0 && value <= 10)
>> >>>>
>> >>>> // passed
>> >>>> }
>> >>>>
>> >>>> How would it be if Swift would allow us to constraint numeric typs with
>> >>>> ranges/intervals?
>> >>>>
>> >>>> func newFoo(value: Int<1...10>) {
>> >>>> // no need for an assertion any more
>> >>>> }
>> >>>>
>> >>>> We could go even further and add more then one range/interval:
>> >>>>
>> >>>> func someFoo(value: Int<0...20, 40...60>) { /* do some work */ }
>> >>>>
>> >>>> Not only integers should have this ability but also floating point
>> >>>> types like Double and Float.
>> >>>>
>> >>>> Alternative form might look like this:
>> >>>>
>> >>>> Double[1.0...10.0]
>> >>>> Float[0.0...1.0, 10.0...100.0]
>> >>>>
>> >>>> One downside of half opened ranges/intervals is the left side of its
>> >>>> set. How do we exclude the left element?
>> >>>>
>> >>>> 1...10 means 1..<11 equals [1, 11)
>> >>>>
>> >>>> But how can we create something like (0.0, 1.0), do we need a strange
>> >>>> looking binary operator 0.0>..<1.0?
>> >>>>
>> >>>> What do you think? I'd love to hear any feedback to this.
>> >>>>
>> >>>> --
>> >>>> Adrian Zubarev
>> >>>> Sent with Airmail
>> >>>> _______________________________________________
>> >>>> swift-evolution mailing list
>> >>>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> >>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> >> _______________________________________________
>> >> swift-evolution mailing list
>> >> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> >> https://lists.swift.org/mailman/listinfo/swift-evolution
>> >
>> >
>> >
>> > _______________________________________________
>> > swift-evolution mailing list
>> > swift-evolution at swift.org
>> > https://lists.swift.org/mailman/listinfo/swift-evolution
>> >
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160518/b6eb0f19/attachment.html>


More information about the swift-evolution mailing list