Why can't I pass arguments with units to F# types? - f#

Suppose I have defined a unit of measure:
[<Measure>] type Blob
And I want a type that takes a value in Blobs per second as a constructor argument:
type Something(flowRate:double<Blob/s>) = ...
F# throws a wobbly on this - "double does not expect any type arguments, but here is given 1 type argument"
I understand the message. I'd have thought it was obvious what I was trying to do, though I acknowledge that the syntax probably is verifiably wrong. Question is, how do I express this relationship in code?

As the message (sort of) indicates, doubles aren't measure-generic. Try float<Blob/s> instead. It's a bit strange, since float is a type synonym for type double. However, type float<[<Measure>]'t> is in some ways its own separate type. A similar problem occurs with single vs. float32, int32 vs. int, and int8 vs. byte. Section 9.7 of the spec partly covers this information.
It's especially confusing since you can't define your own types which differ only in their measure arity:
type T = class end
type T<[<Measure>]'t> = class end //' Duplicate definition of type T

Related

In F#, what do you call a type defined as a function signature

In F#, is there a special name for a type defined in the following manner:
type Foo = int -> string
I ask because such a type seems to have special significance. It is quite abstract compared to other types and seems to only be usable as a sort of function interface. It is not discussed much in F# literature, but it is used quite a bit in the source of many F# OSS projects.
Is it a special sort of type that has some broader significance in functional programming? Does it have other applications other than functioning as a sort of interface for functions? Why is it something that doesn't really make sense to instantiate, even though you can kind of do that by defining a function with a matching type signature? Or is it really just as simple as saying that it is an alias for a function definition which can then be used as a short form in other type signatures/definitions and that accounts for all it's properties?
The name used in the F# documentation for this kind of definition is type abbreviation and I think many people often refer to it as type alias.
The definition defines an alias or a shorter name for a longer type. It says that whenever you type Foo, the compiler will see it as int -> string.
Type abbreviations do not define a new type, which means that Foo and int -> string are equivalent (a value of one type is also a value of the other type). The important points are:
Type inference will generally infer the original type, so when you write a function that matches the type, compiler will infer it as int -> string unless you give an explicit type annotation
When compiled, the abbreviations are erased (because .NET does not have such concept) and so the compiled code will see int -> string.
Abbreviations are useful just for readability reasons - it lets you use more descriptive name for a type. However, they do not have many other implications.

Type classes in Nim

I am trying to make a simple use of typeclasses in Nim. Please, keep in mind that I only have been using Nim since this morning, so I may have been doing something stupid.
Anyway, I would like to define a pseudorandom generator that produces a stream of values of type T. Sometimes T is numeric, hence it makes sense to know something about the minimum and maximum values attainable - say to rescale the values. Here are my types
type
Generator*[T] = generic x
next(var x) is T
BoundedGenerator*[T] = generic x
x is Generator[T]
min(x) is T
max(x) is T
I also have such an instance, say LinearCongruentialGenerator.
Say I want to use this to define Uniform generator that produces float values in an interval. I have tried
type Uniform* = object
gen: BoundedGenerator[int]
min_p: float
max_p: float
proc create*(gen: BoundedGenerator[int], min: float, max: float): Uniform =
return Uniform(gen: gen, min_p: min, max_p: max)
I omit the obvious definitions of next, min and max.
The above, however, does not compile, due to Error: 'BoundedGenerator' is not a concrete type
If I explicitly put LinearCongruentialGenerator in place of BoundedGenerator[int], everyting compiles, but of course I want to be able to switch more sophisticated generators.
Can anyone help me understand the compiler error?
The type classes in Nim are not used to create abstract polymorphic types as it is the case with Haskell's type classes and C++'s interfaces. Instead, they are much more similar to the concepts proposal for C++. They define a set of arbitrary type requirements that can be used as overload-resolution criteria for generic functions.
If you want to work with abstract types, you can either define a type hierarchy with a common base type and use methods (which use multiple dispatch) or you can roll your own vtable-based solution. In the future, the user defined type classes will gain the ability to automatically convert the matched values to a different type (during overload resolution). This will make the vtable approach very easy to use as values of types with compatible interfaces will be convertible to a "fat pointer" carrying the vtable externally to the object (with the benefit that many pointers with different abstract types can be created for the same object). I'll be implementing these mechanisms in the next few months, hopefully before the 1.0 release.
Araq (the primary author of Nim) also has some plans for optimizing a certain type of group of closures bundled together to a cheaper representation, where the closure environment is shared between them and the end result is quite close to the traditional C++-like vtable-carrying object.

F# type definition using `of` keyword

Let me state that I am very green in F# (but 4 years experience in C#). I wanted to start learning F# and I was following the TryFSharp.org tutorials. I came to the point of the computation expressions but things weren't exactly clear. So I started to google it. I came across another tutorial / article which explained it a lot better in the first example (the logging example). But then I read on and came to the second example; I cannot follow the flow of the code or how it is supposed to work, perhaps because I don't understand the definition of the State type:
type State<'a, 's> = State of ('s -> 'a * 's)
I have worked with a few simple types in F# already, I have seen struct, class, record but I have no clue how to read this type or what it is supposed to do. I also can't figure out what the of keyword is doing in there.
So my question is: what does this type definition do / what does the of keyword in it do?
The code defines a discriminated union type named State whose only constructor is also named State and takes an argument of type 's -> 'a * 's. The of keyword separated the constructor name from its argument type.
So basically it says that a State is a function of type 's -> 'a * 's, but you need to use the State constructor to create a State and thus have to write let myState = State someFunction rather than let myState = someFunction.
As already stated, State is a single case discriminated union type. A two-case union type would look like:
type Multi =
| First of name:string
| Second of number:int
One way to think of this is Multi as a base class and First and Second as subclasses where First requires a string in the constructor and Second requires an int. This is a very powerful construct not available in C#. It is powerful because you can pattern match of values of this type and the compiler will force you to handle every case.
A single case union is helpful as a wrapper of another type. In your example, the State type wraps a function from type 's to a pair (C# tuple) 'a * 's. It turns out that this is a very interesting type because it forms a monad and as a result you get all sorts of functions around it. For example, this gist shows how the State monad can be used to implement functional random value generators.

F# Type Inference

I am kind of new to F# so maybe my question is dumb. I wrote a program in F# that used generic types. Compiler determined the types not the way that I desired because I had a bug in the deepest function call that I had instantiated the type to a wrong type. This obviously resulted in type mismatch elsewhere that I had used the type as I had expected. I have to mention to find the root of problem I tried to explicitly enforce the higher level functions to use the types that I desired for the generic type. However the type mismatch was shown in those high-level functions not for the low level function were the type was instantiated. I think it's not very convenient way of determining types because usually it is much easier for programmers to determine the type on higher level functions and this explicit type assignment should result in type error in lower level function were the type has been determined. In my experience it seems automatic type determination of the compiler overrides the explicit type declaration. Am I understanding something wrong here?
Something like the code below:
type test<'a,'b>={Func:'a->'b; Arg:'a}
let C(a)=
a.Func(2)|>ignore
let B(a)=
C(a)
let A(a:test<int64,int64>)=
B(a) //<-----------------------the type mismatch is detected here
Having the error detected on such high level function call makes it difficult to find the root of the problem because now not only I have to look for the bugs regarding the value of variables but also the type determination bugs.
F#'s type inference is (fairly) strict top-to-bottom, left-to-right. See here for a discussion: Why is F#'s type inference so fickle?
You can check this by rearranging your code like this (just for demonstration):
type test<'a,'b>={Func:'a->'b; Arg:'a}
let rec B(a)=
C(a)
and A(a:test<int64,int64>)=
B(a)
and C(a)=
a.Func(2)|>ignore // type mismatch now here
The convenience level depends mostly on the concrete code, in my experience. But I have to admit that I too have sometimes been surprised by type mismatch error messages. It takes some time getting used to.

What is the effect of type synonyms on instances of type classes? What does the TypeSynonymInstances pragma in GHC do?

I'm reading Real World Haskell Pg 151, and I've stared at the following passage for over an hour:
Recall that String is a synonym for
[Char], which in turn is the type [a]
where Char is substituted for the type
parameter a. According to Haskell 98's
rules, we are not allowed to supply a
type in place of a type parameter when
we write an instance. In other words,
it would be legal for us to write an
instance for [a], but not for [Char].
16 comments 5335
It simply isn't sinking in. Staring at the the (free not pirated) copy of RWH chapter 6 I see a lot of other people are really suffering with this. I still don't understand it from the comments...
Firstly, everything about this confuses me, so please if you feel you can explain anything about this passage, or TypeSynonymInstances please do.
Here is my problem:
Int is a data constructor
String is a data constructor AND type synonym
Now I can't answer these questions:
Why would a type synonym preclude the making the type a member of a type class (I'm looking for some reason which probably relates to compilation or implimentation of a type synonym)?
Why did the designers of the language, not want this syntax (I'm asking for reasoning not extensive theory or unicode math symbols).
I see this line "the type [a] where Char is substituted for the type parameter a", and I want to know why I can't substitute it for this "the type a where Int is substituted for the type parameter a".
Thanks!
I think part of the issue is that two, largely unrelated, restrictions are in play:
No type synonym instances means that instances can only be things declared with data or newtype, not type. This forbids String, but not [Char].
No flexible instances means that instances can only mention one type that isn't a variable, and only that type can be used as a type constructor. This forbids Maybe Int and f Int, but not Maybe a.
Here's what GHCi says about Int, Char, and String:
data Char = GHC.Types.C# GHC.Prim.Char#
data Int = GHC.Types.I# GHC.Prim.Int#
type String = [Char]
Int and Char are both simple types without type variable parameters; there's no type constructor involved, so you can make instances with them pretty much freely.
String, however, fails on both counts. It's a type synonym, which isn't allowed, and it's also a type constructor applied to a non-variable, namely the list type constructor applied to Char.
For comparison, note that [a], Maybe a, and Either a b are all valid in instances, but [Int], Maybe [a], and Either String a are forbidden; hopefully you can now see why.
As for your direct questions, I don't know what the original motivations were for designing the language that way, and I'm in no way qualified to make authoritative statements about "best practices", but for my own personal coding I don't really hesitate to use these pragmas:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
You could always go look at packages that use pragmas. Flexible instances, it seems, do get a fair amount of use, and from "respectable" packages (there's a couple hits in the source for Parsec, for instance).
Actually, neither Int nor String are data constructors. That is, you can't use them to create a value of
> (Int 42, String "bob")
<interactive>:1:1: Not in scope: data constructor `Int'
<interactive>:1:9: Not in scope: data constructor `String'
Int names a new, distinct, algebraic data type. String is a "type-synonym", or alias, for the already existing type: [Char]. The problem is that Haskell 98 says you can't use a type synonym in an instance declaration.
I can't say why authors of the Haskell 98 report choose to restrict type synonyms in this case. There are quite a number of restrictions on them. For example, they cannot be partially applied (if they take type arguments). I think a clue comes at the end of ยง4.2.2:
Type synonyms are a convenient, but
strictly syntactic, mechanism to make
type signatures more readable. A
synonym and its definition are
completely interchangeable, except in
the instance type of an instance
declaration (Section 4.3.2).
Presumably, there was an approach to program compilation, for which this syntactic interchangeability would have caused problems for instances. Perhaps it has to do with notable aspect of instances that they leak out of packages...
As to your last question, I believe that explanation is conflating two things: 1) String is a type synonym for [Char], which is in turn a specialization of the more general type [a] and 2) that even without the synonym, [Char] cannot be used in the head of an instance.
This second problem has nothing to do with type synonyms, but that instance heads must have all the type parameters to the type constructor be variables, not concrete types. That is, you can't define separate instances for [Int] and [Char] for some class, you can only defined an instances [a]. (Remember, that despite the convenient syntax, [] is a type constructor, and the thing inside is the type parameter.)
Again, I don't know why the report restricts these, but I suspect it also has to do with compilation strategy. Since GHC's compilation strategy for instances can handle this, you can relax this constraint in GHC via -XFlexibleInstances.
Finally, I've seen both extensions turned on in quite a lot of code, but perhaps someone with more Haskell experience can weigh in as to if they are "best practices" or no.
Haskell 98
an instance head must have the form C (T u1 ... uk), where T is a type constructor defined by a data or newtype declaration (see TypeSynonymInstances) and the ui are distinct type variables, and
each assertion in the context must have the form C' v, where v is one of the ui.
So it is valid to use instance ClassName TypeConstructor where and TypeConstructor MUST be such as Int, Double or [a], make sure that only can a type constructor be involved!!
BTW, [] is type constructor, so [TypeConstructor] cannot be used but [NewType] and [TypeVariable] are allowed.
This is a restriction is Haskell, and we can avoid it by enabling FlexibleInstances.
Int and String are types, not data construtors. String happens to be an alias for [Char] which can also be written List Char. A data constructor is something like Just, so Just 3 is a value of type Maybe Int. Type synonym instances are explained here:
http://hackage.haskell.org/trac/haskell-prime/wiki/TypeSynonymInstances

Resources