Multiple items union case City.City: string -> City
-------------------- type City = | City of string
Full name: Index.SingleCase.City
val city : City
Full name: Index.SingleCase.city
val cityName : City -> string
Full name: Index.SingleCase.cityName
val name : string
val result : string
Full name: Index.SingleCase.result
type City = | CityName of string
Full name: Index.BreakDown.City
union case City.CityName: string -> City
val city : City
Full name: Index.BreakDown.city
val cityName : input:City -> string
Full name: Index.BreakDown.cityName
val input : City
val x : string
val result : string
Full name: Index.BreakDown.result
type ILocatable = interface abstract member Latitude : float abstract member Longitude : float end
Full name: Index.ILocatable
abstract member ILocatable.Latitude : float
Full name: Index.ILocatable.Latitude
Multiple items val float : value:'T -> float (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.float
-------------------- type float = System.Double
Full name: Microsoft.FSharp.Core.float
-------------------- type float<'Measure> = float
Full name: Microsoft.FSharp.Core.float<_>
abstract member ILocatable.Longitude : float
Full name: Index.ILocatable.Longitude
type Place = {Name: string; Latitude: float; Longitude: float;} interface ILocatable
Full name: Index.FirstTry.Place
Place.Name: string
Place.Latitude: float
Place.Longitude: float
val this : Place
override Place.Latitude : float
Full name: Index.FirstTry.Place.Latitude
override Place.Longitude : float
Full name: Index.FirstTry.Place.Longitude
type Place = {Name: string; Latitude: float option; Longitude: float option;} member GetLocation : unit -> ILocatable option
Full name: Index.OptionalLocation.Place
Place.Latitude: float option
type 'T option = Option<'T>
Full name: Microsoft.FSharp.Core.option<_>
Place.Longitude: float option
member Place.GetLocation : unit -> ILocatable option
Full name: Index.OptionalLocation.Place.GetLocation
union case Option.Some: Value: 'T -> Option<'T>
val lat : float
val lng : float
val this : ILocatable
property ILocatable.Latitude: float
property ILocatable.Longitude: float
union case Option.None: Option<'T>
val houston : Place
Full name: Index.OptionalLocation.houston
member Place.GetLocation : unit -> ILocatable option
val camelot : Place
Full name: Index.OptionalLocation.camelot
type Location = {Latitude: float; Longitude: float;}
Full name: Index.Revised.Location
Location.Latitude: float
Location.Longitude: float
type Place = {Name: string; Location: Location option;}
Full name: Index.Revised.Place
Multiple items Place.Location: Location option
-------------------- type Location = {Latitude: float; Longitude: float;}
Full name: Index.Revised.Location
val houston : Place
Full name: Index.Revised.houston
Place.Location: Location option
val camelot : Place
Full name: Index.Revised.camelot
Multiple items type MeasureAttribute = inherit Attribute new : unit -> MeasureAttribute
Full name: Microsoft.FSharp.Core.MeasureAttribute
-------------------- new : unit -> MeasureAttribute
[<Measure>] type degLat
Full name: Index.degLat
[<Measure>] type degLng
Full name: Index.degLng
val degreesLatitude : x:float<'u> -> float<'u degLat>
Full name: Index.degreesLatitude
val x : float<'u>
val degreesLongitude : x:float<'u> -> float<'u degLng>
Full name: Index.degreesLongitude
val degLatResult : float<degLat>
Full name: Index.degLatResult
val degLngResult : float<degLng>
Full name: Index.degLngResult
module SingleCase
from Index
type Location = {Latitude: float<degLat>; Longitude: float<degLng>;}
Full name: Index.UnitsOfMeasure.Location
Location.Latitude: float<degLat>
Location.Longitude: float<degLng>
type Place = {Name: City; Location: Location option;}
Full name: Index.UnitsOfMeasure.Place
Place.Name: City
Multiple items Place.Location: Location option
-------------------- type Location = {Latitude: float<degLat>; Longitude: float<degLng>;}
Full name: Index.UnitsOfMeasure.Location
Multiple items union case City.City: name: string -> City
-------------------- type City = | City of name: string static member Create : name:string -> City
Full name: Index.City
static member City.Create : name:string -> City
Full name: Index.City.Create
val invalidArg : argumentName:string -> message:string -> 'T
Full name: Microsoft.FSharp.Core.Operators.invalidArg
type Location = internal {latitude: float<degLat>; longitude: float<degLng>;} member Latitude : float<degLat> member Longitude : float<degLng> static member Create : lat:float<degLat> * lng:float<degLng> -> Location
Full name: Index.Location
Location.latitude: float<degLat>
Location.longitude: float<degLng>
val this : Location
member Location.Latitude : float<degLat>
Full name: Index.Location.Latitude
member Location.Longitude : float<degLng>
Full name: Index.Location.Longitude
static member Location.Create : lat:float<degLat> * lng:float<degLng> -> Location
Full name: Index.Location.Create
val lat : float<degLat>
val lng : float<degLng>
type Place = {Name: City; Location: Location option;}
Full name: Index.Place
Multiple items Place.Location: Location option
-------------------- type Location = internal {latitude: float<degLat>; longitude: float<degLng>;} member Latitude : float<degLat> member Longitude : float<degLng> static member Create : lat:float<degLat> * lng:float<degLng> -> Location
Multiple items type LiteralAttribute = inherit Attribute new : unit -> LiteralAttribute
Full name: Microsoft.FSharp.Core.LiteralAttribute
-------------------- new : unit -> LiteralAttribute
val ConnStr : string
Full name: Index.ConnStr
type GetCityLocation = SqlCommandProvider<...>
Full name: Index.GetCityLocation
type SqlCommandProvider
Full name: FSharp.Data.SqlCommandProvider
<summary>Typed representation of a T-SQL statement to execute against a SQL Server database.</summary>
<param name='CommandText'>Transact-SQL statement to execute at the data source.</param>
<param name='ConnectionStringOrName'>String used to open a SQL Server database or the name of the connection string in the configuration file in the form of “name=<connection string name>”.</param>
<param name='ResultType'>A value that defines structure of result: Records, Tuples, DataTable, or SqlDataReader.</param>
<param name='SingleRow'>If set the query is expected to return a single row of the result set. See MSDN documentation for details on CommandBehavior.SingleRow.</param>
<param name='ConfigFile'>The name of the configuration file that’s used for connection strings at DESIGN-TIME. The default value is app.config or web.config.</param>
<param name='AllParametersOptional'>If set all parameters become optional. NULL input values must be handled inside T-SQL.</param>
<param name='ResolutionFolder'>A folder to be used to resolve relative file paths to *.sql script files at compile time. The default value is the folder that contains the project or script.</param>
<param name='DataDirectory'>The name of the data directory that replaces |DataDirectory| in connection strings. The default value is the project or script directory.</param>
type LookupLocations = City * City -> Place * Place
Full name: Index.LookupLocations
type TryFindDistance = Place * Place -> float<m> option
Full name: Index.TryFindDistance
type MetersToFeet = float<m> -> float<ft>
Full name: Index.MetersToFeet
type Show = Place * Place * float<ft> option -> string
Full name: Index.Show
val lookupLocation : City -> Place
Full name: Index.lookupLocation
val cmd : GetCityLocation
val result : Option<SqlCommandProvider<...>.Record>
static member Location.Create : lat:float<degLat> * lng:float<degLng> -> Location
val lookupLocations : start:City * dest:City -> Place * Place
Full name: Index.lookupLocations
val start : City
val dest : City
namespace System
namespace System.Device
namespace System.Device.Location
val toGeoCoordinate : _arg1:Location -> GeoCoordinate
Full name: Index.toGeoCoordinate
Multiple items type GeoCoordinate = new : unit -> GeoCoordinate + 3 overloads member Altitude : float with get, set member Course : float with get, set member Equals : obj:obj -> bool + 1 overload member GetDistanceTo : other:GeoCoordinate -> float member GetHashCode : unit -> int member HorizontalAccuracy : float with get, set member IsUnknown : bool member Latitude : float with get, set member Longitude : float with get, set ...
Full name: System.Device.Location.GeoCoordinate
-------------------- GeoCoordinate() : unit GeoCoordinate(latitude: float, longitude: float) : unit GeoCoordinate(latitude: float, longitude: float, altitude: float) : unit GeoCoordinate(latitude: float, longitude: float, altitude: float, horizontalAccuracy: float, verticalAccuracy: float, speed: float, course: float) : unit
val findDistance : start:Location * dest:Location -> float<m>
Full name: Index.findDistance
val start : Location
val dest : Location
val tryFindDistance : Place * Place -> float<m> option
type Stage = | AwaitingInput | InputReceived of start: City * dest: City | Located of start: Place * dest: Place | Calculated of Place * Place * float<m> option | Show of Place * Place * float<ft> option
Full name: Index.Stage
union case Stage.AwaitingInput: Stage
union case Stage.InputReceived: start: City * dest: City -> Stage
union case Stage.Located: start: Place * dest: Place -> Stage
union case Stage.Calculated: Place * Place * float<m> option -> Stage
Multiple items union case Stage.Show: Place * Place * float<ft> option -> Stage
-------------------- type Show = Place * Place * float<ft> option -> string
Full name: Index.Show
type RunWorkflow = Stage -> string
Full name: Index.RunWorkflow
val runWorkflow : _arg1:Stage -> string
Full name: Index.runWorkflow
val distance : float<m> option
namespace System.Text
namespace Arachne
module Language
from Arachne
namespace Arachne.Uri
namespace Arachne.Http
module Cors
from Arachne.Http
module Template
from Arachne.Uri
namespace Freya
namespace Freya.Core
Multiple items module Freya
from Freya.Core
-------------------- namespace Freya
-------------------- type Freya<'T> = FreyaState -> Async<'T * FreyaState>
Full name: Freya.Core.Types.Freya<_>
module Operators
from Freya.Core
namespace Freya.Lenses
namespace Freya.Lenses.Http
namespace Freya.Lenses.Http.Cors
namespace Freya.Machine
namespace Freya.Machine.Extensions
namespace Freya.Machine.Extensions.Http
namespace Freya.Machine.Extensions.Http.Cors
namespace Freya.Machine.Router
namespace Freya.Router
val represent : x:string -> Representation
Full name: Index.represent
Multiple items val string : value:'T -> string
Full name: Microsoft.FSharp.Core.Operators.string
-------------------- type string = String
Full name: Microsoft.FSharp.Core.string
type Description = {Charset: Charset option; Encodings: ContentCoding list option; MediaType: MediaType option; Languages: LanguageTag list option;}
Full name: Freya.Machine.Extensions.Http.Types.Description
Multiple items union case Charset.Charset: string -> Charset
-------------------- module Charset
from Arachne.Http
-------------------- type Charset = | Charset of string static member Iso88591 : Charset static member Unicode : Charset static member Utf8 : Charset
Full name: Arachne.Http.Charset
property Charset.Utf8: Charset
Multiple items union case MediaType.MediaType: Type * SubType * Parameters -> MediaType
-------------------- module MediaType
from Arachne.Http
-------------------- type MediaType = | MediaType of Type * SubType * Parameters override ToString : unit -> string static member Css : MediaType static member Html : MediaType static member JavaScript : MediaType static member Json : MediaType static member Mapping : Mapping<MediaType> static member Text : MediaType static member Xml : MediaType static member format : (MediaType -> string) static member parameters_ : (MediaType -> Parameters) * (Parameters -> MediaType -> MediaType) static member parse : (string -> MediaType) static member subType_ : (MediaType -> SubType) * (SubType -> MediaType -> MediaType) static member tryParse : (string -> Choice<MediaType,string>) static member type_ : (MediaType -> Type) * (Type -> MediaType -> MediaType)
Full name: Arachne.Http.MediaType
property MediaType.Json: MediaType
Multiple items union case LanguageTag.LanguageTag: Language * Script option * Region option * Variant -> LanguageTag
-------------------- type LanguageTag = | LanguageTag of Language * Script option * Region option * Variant override ToString : unit -> string static member Mapping : Mapping<LanguageTag> static member format : (LanguageTag -> string) static member parse : (string -> LanguageTag) static member tryParse : (string -> Choice<LanguageTag,string>)
type Encoding = member BodyName : string member Clone : unit -> obj member CodePage : int member DecoderFallback : DecoderFallback with get, set member EncoderFallback : EncoderFallback with get, set member EncodingName : string member Equals : value:obj -> bool member GetByteCount : chars:char[] -> int + 3 overloads member GetBytes : chars:char[] -> byte[] + 5 overloads member GetCharCount : bytes:byte[] -> int + 2 overloads ...
class Locatable : ILocatable {
publicfloat Latitude { get; set; }
publicfloat Longitude { get; set; }
}
publicclass Place {
publicstring Name { get; set; }
publicfloat? Latitude { get; set; }
publicfloat? Longitude { get; set; }
public ILocatable GetLocation() {
if (Latitude.HasValue && Longitude.HasValue) {
returnnew Locatable {
Latitude = Latitude.Value,
Longitude = Longitude.Value
};
} else {
returnnull; // Oh noes!
}
}
}
Usage:
1: 2: 3: 4: 5: 6: 7: 8: 9:
var houston =new Place
{
Name ="Houston, TX",
Latitude =29.75293,
// Oops! C# doesn't require all props//Longitude = -95.34876
};
houston.GetLocation();
//> null
Usage for a fictional place:
1: 2: 3: 4: 5: 6: 7:
var camelot =new Place
{
Name ="Camelot",
// Convenient to not have to specify values
};
camelot.GetLocation();
//> null
lethouston:Place=
{
Name="Houston, TX"Latitude=Some29.75293// must provide a valueLongitude=Some-95.34876
}
houston.GetLocation()
//> Some ILocatable...
Usage for fictional place:
1: 2: 3: 4: 5: 6: 7: 8: 9:
letcamelot:Place=
{
Name="Camelot"// must provide values alwaysLatitude=NoneLongitude=None
}
camelot.GetLocation()
//> None
Yuck, right?
Can we do better?
Rethinking ILocatable
"Is-a" vs. "Has-a"
Latitude and Longitude belong together
Refactored Place type (C#)
1: 2: 3: 4: 5: 6: 7: 8: 9:
publicclass Location {
publicfloat Latitude { get; set; }
publicfloat Longitude { get; set; }
}
publicclass Place {
publicstring Name { get; set; }
public Location Location { get; set; }
}
Usage:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
var houston =new Place
{
Name ="Houston, TX",
Location =new Location
{
Latitude =29.75293,
// Oops! C# doesn't require all props//Longitude = -95.34876
}
};
houston.Location
//> Non-null Location with null field that is invalid!
Usage for a fictional place:
1: 2: 3: 4: 5: 6: 7:
var camelot =new Place
{
Name ="Camelot",
Location =null
};
camelot.Location
//> null
typeCity=Cityofname:stringwithstaticmemberCreate (name:string) =matchnamewith
| null | ""->invalidArg"Invalid city""The city name cannot be null or empty."
| x->Cityx
Better than nothing
Revisiting Location
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
typeLocation=internal { latitude:float<degLat>; longitude:float<degLng> }
memberthis.Latitude=this.latitudememberthis.Longitude=this.longitudestaticmemberCreate (lat, lng) =if-90.<degLat>>lat||lat>90.<degLat>theninvalidArg"lat""Latitude must be within the range -90 to 90."elif-180.<degLng>>lng&&lng>180.<degLng>theninvalidArg"lng""Longitude must be within the range -180 to 180."else { latitude=lat; longitude=lng }