[swift-evolution] Epic: Typesafe calculations

Matt Whiteside mwhiteside.dev at gmail.com
Tue Jan 12 16:49:51 CST 2016


Hi Tino, Thanks for making your proposal.

One of the points from your ‘alternatives considered’ section,
> Marked parameters
> 
> It would be possible to keep the parameters in the initializer (or function) and mark them with a keyword: init(static dimensions: Int) {...
> 
got me thinking.  What if parameters marked with static, or constexpr, or some such, could complement template parameters, rather than being an alternative to them.  Basically, stuff between the angle brackets is relevant for determining storage needed, and other constexpr parameters enable arbitrary compile time checks.  I hope the mailing list doesn’t mind a little brainstorming about these further off features.  Probably easiest to explain myself in terms of the matrix example:

struct Matrix<T:ScalarType, NRows:UInt, NCols:UInt>{
  let entries: [ScalarType]

  //note the initializer parameter marked as a constexpr,  
  //which enables further compile time checks with a `where` clause
  init(entries: constexpr [ScalarType] where entries.count == NRows * NCols) {
    self.entries = entries
  }
	
  subscript(i:Int, j:Int) -> ScalarType{
    …
  }	
}

typealias SquareMatrix = Matrix where NRows == NCols

extension SquareMatrix{
  static alias Dim = NRows//no additional storage
  func determinant() -> ScalarType{
    ...
  }
}

struct InvertibleMatrix: SquareMatrix where determinant() != 0 
//                       ^~~ 'restriction’ clause, i.e., not inheritance;
//                       determinant() is executed at compile time,
//                       since `entries` is a constexpr


struct AntisymmetricMatrix: InvertibleMatrix where {
  //more complicated restriction clause, something like a
  //compile time predicate/closure, which operates on member variables that are constexprs
  for i in 0..<Dim{
    for j in 0..<Dim{
      static_assert(entries[i][j] == -entries[j][i], “invalid entries”);
    }
  }
  
}

struct ComplexNumber: AntisymmetricMatrix<Dim: 2> 
		      where entries[0,0] == entries[1,1] 
			    && entries[0,1] == -entries[1,0]

struct Rotor: ComplexNumber where magnitude() == 1.0

func *(lhs:ComplexNumber, rhs:ComplexNumber) -> ComplexNumber{
  return ComplexNumber( entries: [lhs.entries[0,0]* …)
}

//another syntax option this feature:
typerestriction InvertibleMatrix = SquareMatrix where determinant() != 0 

//and another:
typespecialization InvertibleMatrix = SquareMatrix where determinant() != 0 
Some obvious drawbacks here are long compile times (eg, computing a 10x10 determinant), and of course many situations where you can’t know things at compile time so this doesn’t help you.  But I think it’s an interesting direction to look at.  A type system with such capabilities, + playgrounds/REPLs, and you’ve got something akin to Mathematica, but without the mind-bending syntax.

Matt


> On Jan 12, 2016, at 06:22, Tino Heth <2th at gmx.de> wrote:
> 
> Hi there!
> 
> I hope there's still some interest in the topic (or in the cartwheels-video Matt promised ;-) and just finished the draft for a first proposal.
> Instead of trying to turn typealias into some sort of newtype, which leaves a lot more questions open as I thought originally, I started with "compile-time parameters":
> The name of the feature can be discussed (as well as its details), but it would not only add typesafety to matrix, vector, tensor and other entities, but also offer a simple way to handle computations with physical quantities (three of those should be sufficient in most cases, so the idea mentioned by Thorsten should work fine).
> 
> I still haven't taken the time to take a detailed look at boost units, but I would be glad if someone with practical experience could contribute to the proposal — the same is true for all other parts, as I'd happily turn the document into a joint paper (I'm not sure, but maybe it could even become the first multi-author submission :)
> 
> To make this easier, I created a wiki-page; this should be editable without forking a repository (I haven't figured out if a can give write permissions to everyone, so it might be necessary to click somewhere to request permissions).
> The URL is
> https://github.com/SwiftTypesafeCalculations/Home/wiki/Compile-time-parameters
> 
> Happy collaboration!
> Tino

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160112/fe07317a/attachment.html>


More information about the swift-evolution mailing list