Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use a discriminated union branch in a type parameter?

Suppose I have a type like this in F#:

type public Expression =
    | Identifier of string
    | BooleanConstant of bool
    | StringConstant of string
    | IntegerConstant of int
    | Vector of Expression list
    // etc...

Now I want to use this type to build a map:

definitions : Map<Identifier, Expression>

However, this gives the error:

The type 'identifier' is not defined

How can I use my type-case as a type paramter?

like image 681
sdgfsdh Avatar asked Nov 09 '16 08:11

sdgfsdh


People also ask

What is a discriminated union C#?

Discriminated Unions are a functional programming convenience that indicates that something is one of several different types of objects. For example, a User might be an unauthenticated user, a regular user, or an administrator.

How do you use a union in TypeScript?

TypeScript - UnionTypeScript allows us to use more than one data type for a variable or a function parameter. This is called union type. Consider the following example of union type. In the above example, variable code is of union type, denoted using (string | number) .

When would you use an intersection type instead of a union type?

Intersection types are closely related to union types, but they are used very differently. An intersection type combines multiple types into one. This allows you to add together existing types to get a single type that has all the features you need.

Are the unions of F# discriminated?

In this case the new type is the “sum” of the integer type plus the boolean type. In F#, a sum type is called a “discriminated union” type. Each component type (called a union case) must be tagged with a label (called a case identifier or tag) so that they can be told apart (“discriminated”).


2 Answers

Identifier is a case constructor, not a type. It's actually a function with the type string -> Expression. The type of the case is string, so you can define definitions as

type definitions : Map<string, Expression>
like image 67
Mark Seemann Avatar answered Nov 14 '22 19:11

Mark Seemann


There is another way in case you want the key to be a specific type (i.e.) not just another string. You can just create StringID type, and alternatively wrap that further into an Expression:

type StringId = Sid of string
type  Expression =
    | StringId of StringId
    | BooleanConstant of bool
    | StringConstant of string
    | IntegerConstant of int
    | Vector of Expression list

This will let you create a map in either of the following ways:

let x = Sid "x"
[StringId x ,BooleanConstant true] |> Map.ofList
//val it : Map<Expression,Expression> = map [(StringId (Sid "x"), BooleanConstant true)]

[x,BooleanConstant true] |> Map.ofList
//val it : Map<StringId,Expression> = map [(Sid "x", BooleanConstant true)]

That said, keeping the key as a simple string is certainly less complicated.

like image 2
s952163 Avatar answered Nov 14 '22 18:11

s952163