I'd like to define a type that represents a unit vector.
This is what I have currently:
type UVec = UVec Float Float
unit : Float -> Float -> UVec
unit a b =
let
norm = sqrt (a^2 + b^2)
in
UVec (a/norm) (b/norm)
While unit yields what I want, I have no way of ensuring that UVec is always a unit vector in other parts of the program. For example, I could write something like this:
wrong = UVec 100 200
and it would compile just fine.
Is there any way to make the unit function the sole constructor of the UVec type? Or some way to restrict values of UVec?
You could place UVec in a module and only expose what you want:
module UnitVector exposing (UVec, unit, values)
type UVec = UVec Float Float
unit : Float -> Float -> UVec
unit a b =
let
norm = sqrt (a^2 + b^2)
in
UVec (a/norm) (b/norm)
values : UVec -> (Float, Float)
values (UVec a b) =
(a, b)
I've added a function above that allows you to retrieve the values, since you aren't exposing the constructor.
Had you actually wanted to expose the UVec Float Float constructor, you would change the module line to something like:
module UnitVector exposing (UVec(UVec), unit, values)
Related
I want to declare ahead of time the value type for a map type.
The functor Map.Make returns a Map.S with two type definitions:
type key
type !+'a t
Type 'a appears to be the type of values in the map. For example, this is the function for adding a key (of type key and value of type 'a:
val add: key -> 'a -> 'a t -> 'a t
One can write the key type like this:
module type M = Map.S with type key = string
But I couldn't figure out how to specify the value type. This isn't valid syntax:
module type M = Map.S with type key = string and 'a = int
One way to look at this is that you're trying to impose monomorphism in the wrong place. The essence of Map.S is that it's polymorphic in the element type.
You can easily define a type for maps from string keys to int values:
# module M = Map.Make(String);;
. . .
# type string_int_mod = int M.t;;
type string_int_mod = int M.t
# let f (m: string_int_mod) s i = M.add s i m;;
val f : string_int_mod -> M.key -> int -> int M.t = <fun>
In many cases, the polymorphism inferred by OCaml is clearer than specifically ascribed types. At least in my opinion. The types inferred by OCaml tell you what the code is really doing and where it has degrees of freedom.
OCaml unfortunately doesn't accept type variables ranging over type constructors :
'a option, 'a list are valid, but 'a 'm is not.
Thanks to functors (cf so/Fix data type in OCaml) we can encode fix point and range over type constructor.
We can also avoid using modules, and use only value-level Ocaml (Lightweight higher kind cf higher and higher_kind )
Some data structure like perfect trees can be described as a fixpoint of a "higher order functor" : the equivalent to the "underlying type constructor", before taking the fixpoint, maps a type constructor (p: * -> *) to another type constructor * -> *.
Can we encode perfect trees as such a fixpoint using the value-level (LHK) approach of the higher/higher_kind library ?
Perfect = Mu1 (p : *->*). Id + p ∘ Δ
where
Δ : * -> *
type Δ a = (a,a)
in haskell
-- stack --resolver lts-17.10 script
{-# LANGUAGE StandaloneKindSignatures #-}
module SOPerfectTree where
type Perfect :: * -> *
type Perfect a = Mu1 PerfectF a
type Mu1 :: ((* -> *) -> * -> *) -> * -> *
newtype Mu1 f a = In {unIn :: f (Mu1 f) a}
type PerfectF :: (* -> *) -> * -> *
data PerfectF f a = Leaf a | Node (f (a, a))
It is possible to represent to some how make unFix total? Possibly by restricting what f is?
record Fix (f : Type -> Type) where
constructor MkFix
unFix : f (Fix f)
> :total unFix
Fix.unFix is possibly not total due to:
MkFix, which is not strictly positive
The problem here is that Idris has no way of knowing that the base functor you are using for your datatype is strictly positive. If it were to accept your definition, you could then use it with a concrete, negative functor and prove Void from it.
There are two ways to represent strictly positive functors: by defining a universe or by using containers. I have put everything in two self-contained gists (but there are no comments there).
A Universe of Strictly Positive Functors
You can start with a basic representation: we can decompose a functor into either a sigma type (Sig), a (strictly-positive) position for a recursive substructure (Rec) or nothing at all (End). This gives us this description and its decoding as a Type -> Type function:
-- A universe of positive functor
data Desc : Type where
Sig : (a : Type) -> (a -> Desc) -> Desc
Rec : Desc -> Desc
End : Desc
-- The decoding function
desc : Desc -> Type -> Type
desc (Sig a d) x = (v : a ** desc (d v) x)
desc (Rec d) x = (x, desc d x)
desc End x = ()
Once you have this universe of functors which are guaranteed to be strictly positive, you can take their least fixpoint:
-- The least fixpoint of such a positive functor
data Mu : Desc -> Type where
In : desc d (Mu d) -> Mu d
You can now define your favourite datatype.
Example: Nat
We start with a sum type of tags for each one of the constructors.
data NatC = ZERO | SUCC
We then define the strictly positive base functor by storing the constructor tag in a sigma and computing the rest of the description based on the tag value. The ZERO tag is associated to End (there is nothing else to store in a zero constructor) whilst the SUCC one demands a Rec End, that is to say one recursive substructure corresponding to the Nat's predecessor.
natD : Desc
natD = Sig NatC $ \ c => case c of
ZERO => End
SUCC => Rec End
Our inductive type is then obtained by taking the fixpoint of the description:
nat : Type
nat = Mu natD
We can naturally recover the constructors we expect:
zero : nat
zero = In (ZERO ** ())
succ : nat -> nat
succ n = In (SUCC ** (n, ()))
References
This specific universe is taken from 'Ornamental Algebras, Algebraic Ornaments' by McBride but you can find more details in 'The Gentle Art of Levitation' by Chapman, Dagand, McBride, and Morris.
Strictly Positive Functors as the Extension of Containers
The second representation is based on another decomposition: each inductive type is seen as a general shape (i.e. its constructors and the data they store) plus a number of recursive positions (which can depend on the specific value of the shape).
record Container where
constructor MkContainer
shape : Type
position : shape -> Type
Once more we can give it an interpretation as a Type -> Type function:
container : Container -> Type -> Type
container (MkContainer s p) x = (v : s ** p v -> x)
And take the fixpoint of the strictly positive functor thus defined:
data W : Container -> Type where
In : container c (W c) -> W c
You can once more recover your favourite datatypes by defining Containers of interest.
Example: Nat
Natural numbers have two constructors, each storing nothing at all. So the shape will be a Bool. If we are in the zero case then there are no recursive positions (Void) and in the succ one there is exactly one (()).
natC : Container
natC = MkContainer Bool (\ b => if b then Void else ())
Our type is obtained by taking the fixpoint of the container:
nat : Type
nat = W natC
And we can recover the usual constructors:
zero : nat
zero = In (True ** \ v => absurd v)
succ : nat -> nat
succ n = In (False ** \ _ => n)
References
This is based on 'Containers: Constructing Strictly Positive Types' by Abbott, Altenkirch, and Ghani.
Well, I do recognized I'm puzzled with haskell and that this is my first weekend with it.
I just wonder if the following design of a OO-class Point2D
is supposed to be written in Haskell as follows:
import Prelude hiding ( sum )
-- ...............................................................
-- "class type" : types belonging to this family of types
-- must implement distance and sum functions
-- ...............................................................
class PointFamily p where
-- p is a type of this family, not a point
distance :: p -> p -> Float -- takes two things of type p and returns a Real
sum :: p -> p -> p -- takes two things of type p and returns a p thing
-- ...............................................................
-- data type: Point2D
-- a new type with x and y coordinates
-- ...............................................................
data Point2D = Point2D { x :: Float , y :: Float }
deriving (Show) -- it is "showable/printable"
-- ...............................................................
-- Point2D belongs to PointFamily, so let's say it and
-- how to compute distance and sum for this type
-- ...............................................................
instance PointFamily Point2D where
-- ............................................................-
distance p1 p2 = sqrt (dx*dx + dy*dy)
where
dx = (x p1) - (x p2)
dy = (y p1) - (y p2)
-- ............................................................-
sum p1 p2 = Point2D { x = (x p1)+(x p2), y = (y p1)+(y p2) }
-- ...............................................................
-- global constant
-- ...............................................................
origin = Point2D 0.0 0.0
-- ...............................................................
-- main
-- ...............................................................
main = do
putStrLn "Hello"
print b
print $ distance origin b
print $ sum b b
where
b = Point2D 3.0 4.0
Yes, I know I should not try do "think OOP" in Haskell, but ... well, 1) that's going to take a long time, and 2) in practice I guess you're gonna find several OOP designs to be rewriten in Haskell
First off: indeed, you should try not to "think OOP" in Haskell!
But your code isn't really OOP at all. It would be OO if you started to try virtual inheritance etc., but in this example it's more that the OO implementation happens to resemble the obvious Haskell implementation.
Only, it should be emphasised that the type class PointFamily really doesn't have any particular 1:1 relation with the data type Point2D, like their bundling in the OO class. You would in practise make instances of this class for any type where it conceivably works. Unsurprisingly, all of this has been done before; the most widespread equivalent of PointFamily is AffineSpace from the vector-spaces package. That is a lot more general, but has in principle much the same purpose.
Just to illustrate leftroundabout's point about not needing to think OO, I took the liberty of removing the typeclass, to show how straightforward the code can be. Don't vote for this if you currently need the ability to write code that works unmodified against 2D and 3D points. But I suspect what you really need right now is a 2D point and this code does that nicely. This is on the "You ain't gonna need it" principle. If, later, it turns out you do need it, there are several ways of introducing it.
I also added bang patterns on the x and y fields, since typical 2D applications usually want those fields to be strict.
import Prelude hiding ( sum )
data Point2D = Point2D { x :: !Float , y :: !Float }
deriving (Read,Show,Eq)
distance :: Point2D -> Point2D -> Float -- takes two things of type p and returns a Real
distance p1 p2 = sqrt (dx*dx + dy*dy)
where
dx = (x p1) - (x p2)
dy = (y p1) - (y p2)
sum :: Point2D -> Point2D -> Point2D -- takes two things of type p and returns a p thing
sum p1 p2 = Point2D { x = (x p1)+(x p2), y = (y p1)+(y p2) }
origin = Point2D 0.0 0.0
main = do
putStrLn "Hello"
print b
print $ distance origin b
print $ sum b b
where
b = Point2D 3.0 4.0
I was wondering if there are any sweet languages that offer some sort of abstraction for "feet" vs "inches" or "cm" etc. I was considering doing something like the following in Java:
u(56).feet() + u(26).inches()
and be able to get something like
17.7292 meters as the result.
One possible approach is, when making a new value, immediately convert it to a "base" unit, like meters or something, so you can add them easily.
However, I would much rather have the ability to preserve units, so that something like
u(799.95555).feet() - u(76).feet()
returns
723.95555 feet
and not
243.826452 meters - 23.1648 meters = 220.661652 meters
//220.661652 meters to feet returns 723.955551 feet
Since this problem seems like it would be really common, is there any framework or even a programming language that exists that handles this elegantly?
I suppose I can just add the units as they are in my methods, adding matching units together and only converting in order to +-*/ [add/subtract/multiply/divide] when they are requested, which is great for adding and subtracting:
//A
{
this.inches = 36.2;
this.meters = 1;
}
//total length is 1.91948 m
if I add this to an object B with values
//B
{
this.inches = 0.8;
this.meters = 2;
}
//total length is 2.02032 m
and I get a new object that is
{
this.inches = 37;
this.meters = 3;
}
//total length is 3.9398 meters
which is totally awesome, I can convert it whenever I want no problem. But operations such as multiplication would fail ...
//A * B = 3.87796383 m^2
{
this.inches = 28.96;
this.meters = 2;
}
// ...but multiplying piece-wise and then adding
// gives you 2.01868383 m^2, assuming you make 2m*1m give you 2 m^2.
So all I really wanted to show with that example was that
( A1 + A2 ) * ( Z1 + Z2 ) is not ( A1 * Z1 ) + ( A2 * Z2 )
And I'm pretty sure this means one has to convert to a common unit if they want to multiply or divide.
The example was mostly to discourage the reflexive answer, that you add or subtract them piece-wise before converting at the last moment, since * and / will fail.
tl;dr: Are there any clever ways to preserve units in programming? Are there clever ways to name methods/routines such that it's easy for me to understand what I'm adding and subtracting, etc?
I know for a fact there is such a language, although I haven't used it myself.
It's called Frink.
It not only allows you to mix different units for the same dimension but also operate on several different physical measurements. The sample calculations on its site are a fun read. I particular like the Superman bit.
F# has language support for units of measure.
EDIT: See also How do F# Units of Measure work
Many functional languages allow creating types for this sort of unit preservation. In Haskell:
-- you need GeneralizedNewtypeDeriving to derive Num
newtype Feet = Feet {unFeet :: Float} deriving (Eq, Show, Num)
newtype Meters = Meters {unMeters :: Float} deriving (Eq, Show, Num)
Now each unit is its own type, and you can only perform operations on values of the same type:
*Main> let a1 = 1 :: Feet
*Main> let a2 = 2 :: Feet
*Main> let a3 = 3 :: Meters
*Main> a1+a2
Feet 3.0
*Main> a1+a3
<interactive>:1:3:
Couldn't match expected type `Feet' against inferred type `Meters'
In the second argument of `(+)', namely `a3'
In the expression: a1 + a3
In the definition of `it': it = a1 + a3
*Main>
Now you can create a conversion type class to convert to and from any measurement types
class LengthMeasure unit where
untype :: unit -> Float
toFeet :: unit -> Feet
toFeet = Feet . (* 3.2808) . untype . toMeters
toMeters :: unit -> Meters
toMeters = Meters . (* 0.3048) . untype . toFeet
instance LengthMeasure Feet where
untype = unFeet
toFeet = id
instance LengthMeasure Meters where
untype = unMeters
toMeters = id
Now we can freely convert between types:
*Main> a1+toFeet a3
Feet {unFeet = 10.842401}
Of course, packages to do this sort of thing are available in Haskell.
Since you're using Java already, maybe Scala or Clojure would offer similar capabilities?
JSR-275 might be relevant http://code.google.com/p/unitsofmeasure/
See Which jsr-275 units implementation should be used?
I have done a lot of work with Units and there isn't anything comprehensive. You can find a lot of partial utilities (I think there are some distributed with UNIXes). NIST was developing a units markup language but it's been at least a decade cooking.
To do this properly needs an ontology in which the units are defined and the rules for conversion. You also have to deal with prefixes.
If you stick with physical science (SI units) there are 7 (possibly 8) base unit-types and 22 named derived quantities. But there are an also infinote number of ways they can be combined. For example the rate of change of acceleration is called "jerk" by some. In principle you could have an indefinite number of derivatives.
Are currencies units? etc...