how to define a measure as a multiple of another measure - f#

I am attempting to define Isaron to be 43.2 times an Egg, but I am getting an exception:
[<Measure>] type Egg
[<Measure>] type Isaron = (43.2)*(Egg)
error FS0618: Invalid literal in type
How do I correctly define this measure?

You don't define the relationship in the measure type, you define it in functions that convert to and from the types:
[<Measure>] type Egg
[<Measure>] type Isaron
let toEgg (i : float<Isaron>) = i / 43.2<Isaron> * 1.0<Egg>
let toIsaron (e : float<Egg>) = e / 1.0<Egg> * 43.2<Isaron>
Scott Wlaschin's site has another example of how to do it in feet and inches, by creating a constant conversion factor:
[<Measure>] type Egg
[<Measure>] type Isaron
let isaronsPerEgg = 43.2<Isaron/Egg>
let toEgg (i : float<Isaron>) = i / isaronsPerEgg
let toIsaron (e : float<Egg>) = e * isaronsPerEgg

Related

How can I split a float (1,2) into 1 and 2 integers?

I'm learning F# and have an assignment where I have to treat a float as a coordinate. For example float 2.3 would be treated as a coordinate (2.3) where x is 2 and y is 3.
How can I split the float to calculate with it?
I am trying to make a function to calculate the length of a vector:
let lenOfVec (1.2, 2.3) and using pythagoras' method to get the length of hypotenuse.
But I am already stuck at splitting up the float.
Hope some can help!
Having at your disposal libraries as rich as F#/.NET offer the task of splitting a float into two can be done with one short line of code:
let splitFloat n = n.ToString().Split('.') |> Array.map float
library function ToString() converts the argument n (supposedly float) to a string
library functionSplit('.') applied to this string converts it into an array of two strings representing the first number before decimal dot and the second number after the dot
finally this array of 2 strings is converted by applying library function float to the each array element with the help of just another library function Array.map, producing the array of two sought floats
Being applied to a random float number the outlined chain of conversions looks like
123.456 --> "123.456" --> [|123;456|] --> [|123.0;456.0|]
Stealing from a few other answers on here, something like this seems to work for a few examples:
open System
///Takes in a float and returns a tuple of the the two parts.
let split (n: float) =
let x = Math.Truncate(n)
let bits = Decimal.GetBits(decimal n)
let count = BitConverter.GetBytes(bits.[3]).[2]
let dec = n - x
let y = dec * Math.Pow(10., float count)
x, y
Examples:
2.3 -> (2.0, 3.0)
200.123 -> (200.0, 123.0)
5.23 -> (5.0, 23.0)
Getting the X is easy, as you can just truncate the decimal part.
Getting the Y took input from this answer and this one.

How to implement Python class in F#

I have the following simple class implementation in Python. I would like to duplicate the functionality in F#...but I am not sure how...
class MyClass(object):
def __init__(self):
pass
def addEvidence(self,dataX,dataY):
newdataX = np.ones([dataX.shape[0],dataX.shape[1]+1])
newdataX[:,0:dataX.shape[1]]=dataX
# build and save the model
self.model_coefs, residuals, rank, s = np.linalg.lstsq(newdataX, dataY)
def query(self,points):
return (self.model_coefs[:-1] * points).sum(axis = 1) + self.model_coefs[-1]
So, in pseudo-code, the class looks like this:
Class()
self.model_coefs = []
self.residuals = []
self.rank = 0
self.addEvidence(dataX,dataY):
x, y, z = f(dataX,dataY)
self.model_coefs <- x
self.residuals <- y
self.rank <- z
self.query(points)
return ([self.model_coefs[i] * points[i] for i in points].sum()) + self.model_coefs[self.model_coefs.length]
And if there is an F-sharpy way to do this, great--The thing is, the entity is kind of a data-bin with a functional wrapper by design, so I'm not sure how it would be done with functions...
Anyhow, here is my try so far (I'm skipping the linear regression for now..)
namespace Learners
type LinearRegressionLearner() =
member this.ModelCoefficients : int [] = [|0;0|]
member this.Residuals : int[] = [||]
member this.Rank = 0
member this.addEvidence dataX dataY = "expletive"
member this.query (points:int[]) =
points |> Array.iteri(fun i x -> x * this.ModelCoefficients.[i])
I get an error here: points |> Array.iteri(fun i x -> x * this.ModelCoefficients.[i])...I guess this.ModelCoefficients.[i] is a unit and doesn't match x, which is an integer??
Array.iteri (as with all iter functions) expects a function that returns unit – yours returns int. Maybe you want Array.mapi instead?

Currying confusing about assignment

I have following code snippet that use currying:
let multiply x y = x * y
let double = multiply 2
let ten = double 5
I understand the above code, because I remember this code:
Currying is converting a single function of n arguments into n
functions with a single argument each
And then I encounter the following code:
let double2 z = multiply 2 z
double2 5
I do not understand this code at all. Why double2 can be a function?
What's happening in your latter example is really nothing special.
You can basically read it as:
define a function double2 with one argument z,
which is defined as multiply 2 z
Some people might refer to this as "currying" or "partial function evaluation" but really all that's happening here is that you're defining a function that uses another function in its function body.
let double2 z = multiply 2 z
// ^ here you define a parameter
This turns it into a function.

How to use f# constraints for generic calculation functions?

type Point<'t> =
val X : 't
val Y : 't
new(x : 't,y : 't) = { X = x; Y = y }
let clampedSubtract (p1:Point<_>) (p2:Point<_>) =
Point( max (p2.X - p1.X) 0, max (p2.Y - p1.Y) 0 )
If you look at the code above, you will notice, that the function is not implemented as generic as it should be.
First, using the 0 in the max expressions clamps the type to int. But it should be the type of whatever type Point<'t> has and not Point<int>.
But even more important, this function can only work as expected, if signed types are used for `t.
This raises a few questions of mine:
Is there a way to obtain the neutral element (zero) from a generic (number) type?
How can I express a restriction such as "only signed number"?
Is there a way to extend type constraint system in F#?
Thanks, in advance.
The solution to the first question as already answered is to use an inline function together with GenericZero and that's all.
Regarding the signed restriction, actually there's an easy way to restrict it to signed types. Use somewhere the generic unary negation which is defined only for signed types:
let inline clampedSubtract (p1:Point<_>) (p2:Point<_>) =
let zero = LanguagePrimitives.GenericZero
Point( max (p2.X + -p1.X) zero, max (p2.Y + -p1.Y) zero )
let result1 = clampedSubtract (Point(4 , 5 )) (Point(4 , 5 ))
let result2 = clampedSubtract (Point(4y , 5y )) (Point(4y , 5y ))
let result3 = clampedSubtract (Point(4uy, 5uy)) (Point(4uy, 5uy)) // doesn't compile
In general, if you want to restrict any generic function to signed types you can define this function:
let inline whenSigned x = ignore (-x)
let inline clampedSubtract (p1:Point<_>) (p2:Point<_>) =
whenSigned p1.X
let zero = LanguagePrimitives.GenericZero
Point( max (p2.X - p1.X) zero, max (p2.Y - p1.Y) zero )
Finally regarding your third question it's not very clear to me what do you mean with extending the type system. You can create static constraints by yourself, in that sense the system is already extensible.
I did a project sometime ago to emulate some Haskell types, part of the code of that project is still in a module in FsControl there you can have an idea to what level you can play with those constraints.
This makes it generic:
let inline clampedSubtract (p1:Point<_>) (p2:Point<_>) =
let zero = LanguagePrimitives.GenericZero
Point( max (p2.X - p1.X) zero, max (p2.Y - p1.Y) zero )
But there's no way to constrain it to signed primitive types.

Why is this unit of measure being restricted to 1?

I need to be able to represent the same concept with a few different units in F#. For example, I want to represent "distance" using light-years, astronomical units, kilometers and meters. I'd like to use a generic function for doing calculations with these values. This is how I've grouped ly, AU, km, and m together:
[<Measure>] type ly
[<Measure>] type AU
[<Measure>] type km
[<Measure>] type m
[<Measure>] type distance
type UnitValue<[<Measure>] 'u, [<Measure>] 't> =
val conversionFactor : float<'t / 'u>
val value : float<'u>
new (v, cf) = { value = FloatWithMeasure<'u> v; conversionFactor = FloatWithMeasure<'t / 'u> cf }
member this.toUnits = this.value * this.conversionFactor
member this.fromUnits (x : float<'t>) = x / this.conversionFactor
static member (+) (a : UnitValue<'u, 't>, b : UnitValue<_, 't>) =
a.newValue (a.toUnits + b.toUnits)
static member (-) (a : UnitValue<'u, 't>, b : UnitValue<_, 't>) =
a.newValue (a.toUnits - b.toUnits)
static member (*) (a : UnitValue<'u, 't>, b : float) =
a.newValue (a.toUnits * b)
member this.newValue (x : float<'t>) =
new UnitValue<'u, 't>(float (this.fromUnits x), float this.conversionFactor)
//Distance units
type LightYearValue(value) =
inherit UnitValue<ly, distance>(value, 6324.0)
type AstronomicalUnitValue(value) =
inherit UnitValue<AU, distance>(value, 15.0)
type KilometerValue(value) =
inherit UnitValue<km, distance>(value, 0.00001)
type MeterValue(value) =
inherit UnitValue<m, distance>(value, 0.0000000)
This code is called from unit-unaware C#, and can be done by just specifying new LightYearValue(4.2), which will become a UnitValue<ly, distance> in F#, and can be passed to a function expecting a UnitValue<_, distance>. That way, the appropriate units go into the function, and the appropriate units go out. For example, if I passed the function a UnitValue<AU, distance>, I might get back a float<AU / s ^ 2> depending on the calculation--and it would be an appropriate number for the scale.
Feeling pretty happy with this, I start writing an Orbit type:
and Orbit(PeR : UnitValue<_, distance>, ApR : UnitValue<_, distance>, AgP : float, focus : SphericalMass) =
let PeR = PeR
let ApR = ApR
let AgP = AgP
let focus = focus
let Maj = PeR + ApR
let Ecc = (Maj.value - (2.0 * PeR.value)) / Maj.value
let DistanceAt theta =
(Maj.value / 2.0) * (1.0 - Ecc ** 2.0) / (1.0 + Ecc * Math.Cos(theta))
but when I hover my mouse over PeR, it says its type is UnitValue<1, distance>. So what gives? Why doesn't this work? I can write a function taking UnitValue<_, distance> and it works fine! Could it have to do with C# interacting with this code? (the type is extended by a C# class) Is there any way to make this work :(
When declaring type, you need to declare generic type parameters (and also unit parameters) explicitly. The following declaration infers the types correctly:
type Orbit<[<Measure>] 'u, [<Measure>] 'v>
( PeR : UnitValue<'u, distance>, ApR : UnitValue<'v, distance>,
AgP : float, focus : SphericalMass) =
let Maj = PeR + ApR
let Ecc = (Maj.value - (2.0 * PeR.value)) / Maj.value
let DistanceAt theta =
(Maj.value / 2.0) * (1.0 - Ecc ** 2.0) / (1.0 + Ecc * Math.Cos(theta))
(BTW: You don't need to re-assign parameters to local let bindings - they will be accessible automatically, so I removed lines like let ApR = ApR)

Resources