[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