HeterogeneousCollections 1.0.7
dotnet add package HeterogeneousCollections --version 1.0.7
NuGet\Install-Package HeterogeneousCollections -Version 1.0.7
<PackageReference Include="HeterogeneousCollections" Version="1.0.7" />
paket add HeterogeneousCollections --version 1.0.7
#r "nuget: HeterogeneousCollections, 1.0.7"
// Install HeterogeneousCollections as a Cake Addin #addin nuget:?package=HeterogeneousCollections&version=1.0.7 // Install HeterogeneousCollections as a Cake Tool #tool nuget:?package=HeterogeneousCollections&version=1.0.7
HeterogeneousCollections
Type-safe heterogeneous collections for F#.
Concepts
A standard F# list is homogeneous: every list element must have the same type.
An int list
can only contain integers.
The F# standard library does contain heterogeneous collection types, but there are downsides to their use. For example:
System.Collections.IList
can contain different types of object, because it is not generic: every element is of typeobj
. It is therefore highly type-unsafe.Tuple
is heterogeneous: you can construct(3, "hello")
. However, it was not designed to be a list, so it is not at all ergonomic to use this way: you can't use them while being "generic over the length of the list" in the way that genuine lists naturally are.
HeterogeneousCollections models heterogeneous collections at the type level, so that just as with Tuple
you retain type safety when manipulating the list.
Concretely, a HList<'ts>
(for "heterogeneous list") takes a type parameter 'ts
which represents the ordered list of element types.
We use function types to encode pairs at the type level.
For example:
HList<unit>
is the type of the empty list.HList<int -> unit>
is the type of lists of one int element.HList<string -> int -> unit>
is the type of lists where the first element is astring
and the second element is anint
. (That is, it models the same type asTuple<string, int>
.)
The API of HList
is such that you cannot construct an HList
where the type parameter does not indicate a heterogeneous list in this encoding.
The types available
HList<_>
, as described above: heterogeneous lists.HListT<'ts, 'elem>
: like anHList<'ts>
, except every element of the list is a tuple whose first entry is heterogeneous and whose second entry is the specific fixed'elem
(likeint
).HUnion<'ts>
: as a discriminated union is to a tuple, soHUnion<'ts>
is toHList<'ts>
. This type represents "a piece of data which is exactly one of the types encoded in'ts
".SumOfProducts<'ts>
: essentially anHUnion
ofHList
s.
We also provide:
TypeList<'ts>
, which is essentially "the specification of the type of anHList<'ts>
". It contains no meaningful data.
Examples
(No type annotations are necessary to use this library; they're only here for the sake of the examples.)
let testHList : HList<string -> int -> unit> =
HList.empty |> HList.cons 1234 |> HList.cons "Foo"
// No need to `tryHead`: the type asserts the list to be nonempty
HList.head testHList |> shouldEqual "Foo"
let tail : HList<int -> unit> =
HList.tail testHList
let folder =
{ new HListFolder<string> with
member _.Folder<'a> (state : string) (elt : 'a) : string =
state + " " + elt.ToString ()
}
HList.fold folder "" testHList
|> shouldEqual " Foo 1234"
Real-world usages are available in the ShapeSifter library, which uses HeterogeneousCollections
to decompose and manipulate F# types safely.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- TypeEquality (>= 0.3.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on HeterogeneousCollections:
Package | Downloads |
---|---|
ShapeSifter
ShapeSifter is a type-safe datatype-generic programming library for F#. It offers a type-safe and extensible way to inspect, decompose and create values for various kinds of common F# and .NET types. |
GitHub repositories
This package is not used by any popular GitHub repositories.