Advertisement
Guest User

Untitled

a guest
Jul 24th, 2017
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.01 KB | None | 0 0
  1. namespace Units
  2.  
  3. type MeasureType =
  4. | BaseUnit of string
  5. | Multiple of Measure * ValueType
  6. with
  7. member this.BaseUnitName =
  8. let rec traverse = function
  9. | BaseUnit s -> s
  10. | Multiple(Measure(_,m),_) -> traverse m
  11. traverse this
  12. and Measure = Measure of string * MeasureType with
  13. member this.Name = match this with Measure(s,_) -> s
  14. member this.Type = match this with Measure(_,t) -> t
  15. static member Giga (m:Measure) =
  16. Measure("G"+m.Name,Multiple(m,1000000000.0))
  17. static member Mega (m:Measure) =
  18. Measure("M"+m.Name,Multiple(m,1000000.0))
  19. static member Kilo (m:Measure) =
  20. Measure("k"+m.Name,Multiple(m,1000.0))
  21. static member Deci (m:Measure) =
  22. Measure("d"+m.Name,Multiple(m,0.1))
  23. static member Centi (m:Measure) =
  24. Measure("c"+m.Name,Multiple(m,0.01))
  25. static member Milli (m:Measure) =
  26. Measure("m"+m.Name,Multiple(m,0.001))
  27. static member Micro (m:Measure) =
  28. Measure("ยต"+m.Name,Multiple(m,0.0001))
  29. static member ( * ) (v:ValueType,m:Measure) = UnitValue(v,Unit(m,1))
  30. and UnitType =
  31. | Unit of Measure * int
  32. | CompositeUnit of UnitType list
  33. static member Create(m) = Unit(m,1)
  34. override this.ToString() =
  35. let exponent = function
  36. | Unit(_,n) -> n
  37. | CompositeUnit(_) ->
  38. raise (new System.InvalidOperationException())
  39. let rec toString = function
  40. | Unit(s,n) when n=0 -> ""
  41. | Unit(Measure(s,_),n) when n=1 -> s
  42. | Unit(Measure(s,_),n) -> s + " ^ " + n.ToString()
  43. | CompositeUnit(us) ->
  44. let ps, ns =
  45. us |> List.partition (fun u -> exponent u >= 0)
  46. let join xs =
  47. let s = xs |> List.map toString |> List.toArray
  48. System.String.Join(" ",s)
  49. match ps,ns with
  50. | ps, [] -> join ps
  51. | ps, ns ->
  52. let ns = ns |> List.map UnitType.Reciprocal
  53. join ps + " / " + join ns
  54. match this with
  55. | Unit(_,n) when n < 0 -> " / " + toString this
  56. | _ -> toString this
  57. static member ( * ) (v:ValueType,u:UnitType) = UnitValue(v,u)
  58. static member ( * ) (lhs:UnitType,rhs:UnitType) =
  59. let text = function
  60. | Unit(Measure(s,_),_) -> s
  61. | CompositeUnit(us) -> us.ToString()
  62. let normalize us u =
  63. let t = text u
  64. match us |> List.tryFind (fun x -> text x = t), u with
  65. | Some(Unit(s,n) as v), Unit(_,n') ->
  66. us |> List.map (fun x -> if x = v then Unit(s,n+n') else x)
  67. | Some(_), _ -> raise (new System.NotImplementedException())
  68. | None, _ -> us@[u]
  69. let normalize' us us' =
  70. us' |> List.fold (fun (acc) x -> normalize acc x) us
  71. match lhs,rhs with
  72. | Unit(u1,p1), Unit(u2,p2) when u1 = u2 ->
  73. Unit(u1,p1+p2)
  74. | Unit(u1,p1), Unit(u2,p2) ->
  75. CompositeUnit([lhs;rhs])
  76. | CompositeUnit(us), Unit(_,_) ->
  77. CompositeUnit(normalize us rhs)
  78. | Unit(_,_), CompositeUnit(us) ->
  79. CompositeUnit(normalize' [lhs] us)
  80. | CompositeUnit(us), CompositeUnit(us') ->
  81. CompositeUnit(normalize' us us')
  82. | _,_ -> raise (new System.NotImplementedException())
  83. static member Reciprocal x =
  84. let rec reciprocal = function
  85. | Unit(s,n) -> Unit(s,-n)
  86. | CompositeUnit(us) -> CompositeUnit(us |> List.map reciprocal)
  87. reciprocal x
  88. static member ( / ) (lhs:UnitType,rhs:UnitType) =
  89. lhs * (UnitType.Reciprocal rhs)
  90. static member ( + ) (lhs:UnitType,rhs:UnitType) =
  91. if lhs = rhs then lhs
  92. else raise (new System.InvalidOperationException())
  93. and ValueType = float
  94. and UnitValue = UnitValue of ValueType * UnitType with
  95. member this.Value = match this with UnitValue(v,_) -> v
  96. member this.Unit = match this with UnitValue(_,u) -> u
  97. override this.ToString() = sprintf "%O %O" this.Value this.Unit
  98. member this.ToBaseUnit() =
  99. let rec toBaseUnit = function
  100. | UnitValue(v,(Unit(Measure(_,BaseUnit(_)),_))) as x ->
  101. x
  102. | UnitValue(v,Unit(Measure(_,Multiple(quantity,coefficient)),p)) ->
  103. toBaseUnit (UnitValue(v*coefficient, Unit(quantity,p)))
  104. | UnitValue(v,(CompositeUnit(xs))) ->
  105. let v, ys =
  106. (v,[]) |> List.foldBack (fun x (v,ys) ->
  107. let x = toBaseUnit (UnitValue(v,x))
  108. x.Value, x.Unit::ys
  109. ) xs
  110. UnitValue(v, CompositeUnit(ys))
  111. toBaseUnit this
  112. static member private DoesDimensionalUnitMismatchExist lhs rhs =
  113. let rec measures = function
  114. | Unit(m,_) -> Set.singleton (m)
  115. | CompositeUnit(us) ->
  116. us |> List.map measures |> Set.unionMany
  117. measures lhs |> Set.exists (fun x ->
  118. measures rhs |> Set.exists (fun y ->
  119. y.Type.BaseUnitName = x.Type.BaseUnitName
  120. && not (x = y)
  121. )
  122. )
  123. static member (+) (lhs:UnitValue,rhs:UnitValue) =
  124. if lhs.Unit = rhs.Unit then
  125. UnitValue(lhs.Value+rhs.Value, lhs.Unit+rhs.Unit)
  126. else
  127. let x1 = lhs.ToBaseUnit()
  128. let x2 = rhs.ToBaseUnit()
  129. if x1.Unit = x2.Unit then
  130. UnitValue(x1.Value+x2.Value,x1.Unit+x2.Unit)
  131. else
  132. raise (new System.InvalidOperationException())
  133. static member (*) (lhs:UnitValue,rhs:UnitValue) =
  134. if UnitValue.DoesDimensionalUnitMismatchExist lhs.Unit rhs.Unit then
  135. let lhs = lhs.ToBaseUnit()
  136. let rhs = rhs.ToBaseUnit()
  137. UnitValue(lhs.Value*rhs.Value,lhs.Unit*rhs.Unit)
  138. else
  139. UnitValue(lhs.Value*rhs.Value,lhs.Unit*rhs.Unit)
  140. static member (*) (lhs:UnitValue,rhs:ValueType) =
  141. UnitValue(lhs.Value*rhs,lhs.Unit)
  142. static member (/) (lhs:UnitValue,rhs:UnitValue) =
  143. if UnitValue.DoesDimensionalUnitMismatchExist lhs.Unit rhs.Unit then
  144. let lhs = lhs.ToBaseUnit()
  145. let rhs = rhs.ToBaseUnit()
  146. UnitValue(lhs.Value/rhs.Value,lhs.Unit/rhs.Unit)
  147. else
  148. UnitValue(lhs.Value/rhs.Value,lhs.Unit/rhs.Unit)
  149. static member (/) (lhs:UnitValue,rhs:ValueType) =
  150. UnitValue(lhs.Value/rhs,lhs.Unit)
  151.  
  152. module SI =
  153.  
  154. let length = "length"
  155. let time = "time"
  156. let m = Measure("m", BaseUnit(length))
  157. let km = Measure.Kilo(m)
  158. let s = Measure("s", BaseUnit(time))
  159. let milliseconds = Measure.Milli(s)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement