1

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?

user38602
  • 45
  • 3
  • 1
    probably you could have your `UVec` type and `unit` function in a separate module, and export only the `unit` function, so that is the only thing other modules could see – marcosh Jul 22 '16 at 16:48

1 Answers1

4

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)
Chad Gilbert
  • 36,115
  • 4
  • 89
  • 97
  • Was hoping I could do this without adding another module, but looks like this is the way to go. Thanks! – user38602 Jul 22 '16 at 17:33