How to model a subset of a discriminated union in F#? - f#

I want a thing (person, object, whatever) to have abilities (jump, run, etc.). I want some things to only have certain abilities. These are my current types:
type Ability =
| Jump
| Stay
| Run
| Walk
type Person = {
abilities : Ability Set // OK, since a person should be able to do all of the above
}
type InanimateObject = {
abilities : Ability Set // Not OK, it should only be able to "Stay"
}
type ThingWithAbilities =
| Person of Person
| InanimateObject of InanimateObject
I want a caller of my API to be able to ask for a ThingWithAbilities with a specific ability. Example: Give me all objects of ThingWithAbilities that has the ability "Jump". How can I model this in a good way? I want to make it impossible to create an InanimateObject with the ability "jump" in the code.

If you want to do this in a type-safe way, then you'll need to define different types for different sets of abilities:
type InanimateAbility =
| Stay
type AnimateAbility =
| Jump
| Run
| Walk
type Ability =
| Inanimate of InanimateAbility
| Animate of AnimateAbility
type Person = {
abilities : Ability Set
}
type InanimateObject = {
abilities : InanimateAbility Set
}
Here, InanimateAbility is a type for abilities that only inanimate objects have and AnimateAbility is a type for abilities that are unique to animate objects. Ability combines both of these and represents any kind of ability. Person can then have a set of Abilitiy values, but you can restrict abilities of InanimateObject to a set of InanimateAbility values.
This works fine as long as you do not have too many combinations - if you had four different kinds of objects with various subsets of abilities, then it might get messy. In that case, you would probably just use one type with a runtime check to make sure that you only assign allowed abilities to each object.

you could model them seperately and then define your Person/Object types with reference to the atomic abilities
type Jump = Jump
type Stay = Stay
type Run = Run
type Walk = Walk
type Person = {
abilities : Choice<Jump,Stay,Run,Walk> Set
}
type InanimateObject = {
abilities : Stay Set // actually haveing this as a set is a bit odd...but whatever
}
type ThingWithAbilities =
| Person of Person
| InanimateObject of InanimateObject

Related

conditional field in anonymous records, in f#

I often use anonmymous records to build on the go data that will eventually be serialized and returned to be consumed somewhere else. This is very flexible, quick to deal with, etc.
But one thing I'm really missing is the ability to do something like this pseudo code:
{|
SomeData = 3
StartTime = ....
if ProcessedFinished then yield { EndTime = ... }
|}
when I could add a field, or not, based on some conditions.
Is there a solution to have the flexibility of the anonymous record, yet have the ability to make conditions like this? I could do a dictionary, then insert values based on conditions but then I'd have to box all the values as well and it would be messy right away.
What you're after is not possible today, but you can get pretty close like so:
let initialData =
{|
SomeData = 3
StartTime = ....
|}
if ProcessedFinished then
{| initialData with EndTime = ... |}
else
initialData
Of course, to represent this as a return type it's now more involved, as you'll likely need to use SRTP in the signature to account for any type with a SomeData and StartTime member on it. It's perfectly fine if this is just in the body of a routine that then produces another result to return, though.
If you want to represent data that may be optionally available based on a condition, especially if you want it to live outside of a given function, I'd recommend an option for that field instead.

Rails - Associating database/models with Modules that aren't database tables

I want to create "associations" (or an equivalent concept with similar methods available from having associations). It is with this table of information, that does NOT need to be updated wahtsoever with other tables that DO involve CRUD.
This is my non-updated table of information:
Table name: Personalities
personality_type | alternate_name | CF1 | CF2 | CF3 | CF4 | CF5 | CF6 | CF7 | CF8
----------------------------------------------------------------------------------
ENTj | ENTJ | Te | Ni | Se | Fi | etc | etc | |
INTp | INTJ | (more data values)
ISFj | ISFP | (more data values)
ESFp | ESFP | (more data values)
So it seems to me that making this non-updated into a database table and performing queries on it would be a silly and pointless way of designing my code, since that would entail all of the query loading time overhead.
So I was thinking of something like making a separate Ruby module, but wasn't sure how to "associate" it with other tables that would be full-fledged database tables with models.
1) How do I associate a non-database class instance based on ActiveRecords::Base with one?
2) Which format/data type should I put my non-updated table of information in? class, module, multiple class instances, a 2 dimensional array, or 2 dimensional hash?
My goal in sorting out this decision is to be able to use the similar method notations that comes with associating database models. (e.g. two tables called "Personality" and "User" would allow Rails/Ruby code like #user.alternate_name. and #personality.user.email).
3) Does the fact that rails uses hidden :id, and timestamp columns affect this in any way?
(If this question is a bit broad, feel free to ignore answering it).
Much thanks!
-A user can have only one personality type.
-Other database models need to refer to personality type information independent of the user model.
Presumably only the User model can have a personality type. Why not create an array of these types as a constant in the User model, which you can then refer to in forms etc for selection using User::PERSONALITY_TYPES.
For example:
class User
PERSONALITY_TYPES = %w{ ENTJ INTJ ISFP ESFP }
# ... other model code
end
Then simply store the index of the personality type within the array as the user's personality_type_index.
Perhaps I'm oversimplifying your needs, but this is the approach I would start with.

customising GORM basic collections

As well as associations between different domain classes, GORM also supports mapping of basic collection types. . For example, the following class creates a nicknames association that is a Set of String instances
class Person {
static hasMany = [nicknames:String]
}
This will store the nicknames in a separate table person_nicknames:
---------------------------------------------
| person_id | nickname |
---------------------------------------------
| 1 | Fred |
---------------------------------------------
By default both columns are nullable and there are no indices present. I would like to make the following changes
make both columns not null
put a composite unique index on (person_id, nickname)
Obviously I could just run an SQL script to make these changes, but is it possible for me to express this in the domain model, so that GORM does it when creating and updating the schema?
No, this presently isn't possible. You can fake it by making Nickname an explicit domain class (Andre Steingress gives an example in the question comments), but otherwise you have to write a migration.
You can use joinTable and basic collection types.
http://grails.org/doc/2.4.3/ref/Database%20Mapping/joinTable.html
You can specify SQL behavior with column mapping:
http://grails.org/doc/2.4.3/ref/Database%20Mapping/column.html

Persist column order from Grails domain to database

When Grails creates a table from a domain object, is it possible to specify the column order? I'd like it to preserve the column order as specified in the domain. Instead, it seems to be mostly alphabetical. I could not find anything in the documentation. I've found this article that details specifying constraints, but that did not appear to fix the issue for database columns.
Example:
class Foo {
Long id
String zee
Integer baz
Integer bar
}
I'd like the database columns to then be ordered as:
id | zee | baz | bar
Instead I get something closer to:
id | bar | baz | zee
You can always create the DB outside of Grails and put the columns in whatever order you wish and Grails will happily use the schema you provide (assuming only the column ordering is different from what it wants to create by default)
An even better option, as #Burt pointed out, is to use the database migration plugin to create (and manage) the database. It lets you have fine-grained control over the database in a database-agnostic way and also has the massive advantage of making your DB schema and schema changes versioned along with your code, for both upgrades and rollbacks.
This is the only way to do it as I know. Use static constraints and write them with your order
class Foo {
Long id
String zee
Integer baz
Integer bar
}
static constraints = {
id()
zee()
baz()
bar()
}

F# -> Seq to Map

I'm trying to load all my Categories from the database and then map them to a Map (dictionary?), however when I use the following code:
[<StructuralComparison>]
type Category = {
mutable Id: string;
Name: string;
SavePath: string;
Tags: ResizeArray<Tag> }
let categories = session.Query<Category>()
|> Seq.map(fun z -> (z,0))
|> Map.ofSeq
it simply throws an error that says:
The struct, record or union type
'Category' has the
'StructuralComparison' attribute but
the component type 'ResizeArray'
does not satisfy the 'comparison'
constraint
I have absolutely no clue about what to do, so any help is appreciated!
F# is rightly complaining that ResizeArray<_> doesn't support structural comparison. ResizeArray<_> instances are mutable and don't support structural comparison, and you therefore can't use them as fields of records which are used as keys to Map<_,_>s (which are sorted by key). You have a few options:
Have Tags use a collection type that does support structural comparison (such as an immutable Tag list).
Use [<CustomComparison>] instead of [<StructuralComparison>], which requires implementing IComparable.
Use a mutable dictionary (or another relevant collection type) instead of a Map. Try using the dict function instead of Map.ofSeq, for instance.
The problem here is that by adding StructuralComparison attribute to the type Category you've asked F# to use structural comparison when comparing instances of Category. In short it will compare every member individually to see if they are equal to determine if two instances of Category are equal.
This puts an implicit constraint on every member of Category to themselves be comparable. The type ResizeArray<Tag> is generating an error because it's not comparable. This is true for most collection types.
In order to get rid of this error you'll need to make the ResizeArray<T> type comparable or choose a different key for the Map. Don has a great blog post that goes into this topic in depth and provides a number of different ways to achieve this. It's very much worth the read
http://blogs.msdn.com/b/dsyme/archive/2009/11/08/equality-and-comparison-constraints-in-f-1-9-7.aspx

Resources