[swift-evolution] Epic: Typesafe calculations

Thorsten Seitz tseitz42 at icloud.com
Thu Jan 7 12:46:09 CST 2016


Really great to hear that you are planning for Swift to be able to do these kinds of things!

I tried to see how far I could get (working from memory of a Haskell library; Boost.Units seems quite similar at first glance), but failed of course because of the missing parameterized recursive typealiases:

import Foundation

public protocol Peano {}
public struct Zero : Peano {}
public struct Succ<P : Peano> : Peano {}
public struct Pred<S : Peano> : Peano {}
public typealias One = Succ<Zero>
public typealias Two = Succ<One>
public typealias MinusOne = Pred<Zero>
public typealias MinusTwo = Pred<One>

// Quantity with SI Units

// TODO: extend by more type parameters for the remaining SI units
public struct Quantity<Length: Peano, Time: Peano, Mass: Peano> : Equatable, Comparable {
    
    let value: Double
    
    init(_ value: Double) {
        self.value = value
    }
}

public func ==<L,T,M>(lhs: Quantity<L,T,M>, rhs: Quantity<L,T,M>) -> Bool {
    return lhs.value == rhs.value
}

public func <<L,T,M>(lhs: Quantity<L,T,M>, rhs: Quantity<L,T,M>) -> Bool {
    return lhs.value < rhs.value
}

public func +<L,T,M>(lhs: Quantity<L,T,M>, rhs: Quantity<L,T,M>) -> Quantity<L,T,M> {
    return Quantity<L,T,M>(lhs.value + rhs.value)
}

// Missing language feature: parameterized recursive typealias
// i.e. the following typealiases are currently not possible
typealias Add<Zero, P: Peano> = P
typealias Add<P: Peano, Zero> = P
typealias Add<Succ<P1>, Succ<P2>> = Add<Succ<Succ<P1>>,P2>
typealias Add<Succ<P1>, Pred<P2>> = Add<P1,P2>
typealias Add<Pred<P1>, Succ<P2>> = Add<P1,P2>
typealias Add<Pred<P1>, Pred<P2>> = Add<P1,Pred<Pred<P2>>>

typealias Sub<Zero, P: Peano> = P
typealias Sub<P: Peano, Zero> = P
typealias Sub<Succ<P1>, Succ<P2>> = Sub<P1,P2>
typealias Sub<Succ<P1>, Pred<P2>> = Sub<P1,Pred<Pred<P2>>
typealias Sub<Pred<P1>, Succ<P2>> = Sub<Pred<Pred<P1>>,P2>
typealias Sub<Pred<P1>, Pred<P2>> = Sub<P1,P2>

public func *
    <L1,T1,M1,L2,T2,M2,L,T,M where
    L == Add<L1,L2>, T == Add<T1,T2>, M == Add<M1,M2>>
    (lhs: Quantity<L1,T1,M1>, rhs: Quantity<L2,T2,M2>) -> Quantity<L,T,M>
{
    return Quantity<L,T,M>(lhs.value * rhs.value)
}

public func /
    <L1,T1,M1,L2,T2,M2,L,T,M where
    L == Sub<L1,L2>, T == Sub<T1,T2>, M == Sub<M1,M2>>
    (lhs: Quantity<L1,T1,M1>, rhs: Quantity<L2,T2,M2>) -> Quantity<L,T,M>
{
    return Quantity<L,T,M>(lhs.value / rhs.value)
}


// Defining some nice typealiases with which to work

public typealias Scalar   = Quantity<Zero, Zero, Zero> // dimensionless
public typealias Length   = Quantity<One, Zero, Zero> // meter
public typealias Time     = Quantity<Zero, One, Zero> // seconds
public typealias Mass     = Quantity<Zero, Zero, One> // kilogram
public typealias Velocity = Quantity<One, MinusOne, Zero> // m/s
public typealias Newton   = Quantity<One, MinusTwo, One> // m*kg/s^2


public extension Double {
    
    public var m: Length {
        return Length(self)
    }
    public var s: Time {
        return Time(self)
    }
    public var kg: Mass {
        return Mass(self)
    }
}

let dist = 10.m + 5.m
let time = 20.s
let mass = 5.kg
let velocity: Velocity = dist / time
let force: Newton = mass * dist / (time * time)


-Thorsten


> Am 31.12.2015 um 18:25 schrieb Dave Abrahams via swift-evolution <swift-evolution at swift.org>:
> 
>> 
>> On Dec 25, 2015, at 4:43 PM, Nickolas Pohilets via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> 
>> If Swift would support non-type generic parameters, then I would like to have Boost.Unit library (http://www.boost.org/doc/libs/1_60_0/doc/html/boost_units.html <http://www.boost.org/doc/libs/1_60_0/doc/html/boost_units.html>) available in Swift.
> 
> Yes, that’s an excellent design.  We really want to do this when we get the necessary language features (I hope we might also come up with some that improve readability a bit over what you can do in C++).
> 
>> 
>> 2015-12-25 4:36 GMT+01:00 Stephen Christopher via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>>:
>> I have been working for a couple weeks (since the previous [newtype discussion](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/001821.html <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/001821.html>) ) on a related pitch. There seem to me to be multiple ways to solve this problem - a newtype(esque) keyword, struct subtyping, or forwarding as Matthew is suggesting. I’d hoped to have a discussion starter out before the holidays, but it takes a fair amount of work to put together even a decent draft for a proposal. This is top of my list currently for a way to contribute though. Looking forward to the ensuing discussions.
>> 
>> Thanks for the pointer on class delegation. I’ve looked at delegated properties there (which came up in relation to Joe’s recent proposal for behaviors on properties).
>> 
>> - Step Christopher
>> 
>> 
>> 
>> On Thu, Dec 24, 2015 at 2:40 PM, Matthew Johnson via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> 
>> 
>> Sent from my iPad
>> 
>> > On Dec 24, 2015, at 1:07 PM, Tino Heth <2th at gmx.de <mailto:2th at gmx.de>> wrote:
>> >
>> >
>> >> I'm planning to write a proposal for automatic forwarding.
>> > Something like class delegation in Kotlin?
>> > Please hurry, I've no work to distract me for the rest of the year, and extending typealias could be a very quick proposal ;-)
>> 
>> Details are still brewing.  I am not familiar with class delegation in Kotlin but will look it up.  Thanks for mentioning it!
>> 
>> I plan to spend a lot of time on Swift proposal work over the next week and a half but can't make any promises on timing.  I made that mistake with my proposal on flexible memberwise initialization which ended up taking a couple weeks longer than I expected (for several reasons).  What I can say is that this is pretty high on my Swift proposal priority list.
>> 
>> Matthew
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution <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 <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 <https://lists.swift.org/mailman/listinfo/swift-evolution>
> -Dave
> 
>  _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160107/c1aa50a6/attachment-0001.html>


More information about the swift-evolution mailing list