I was curious about F#'s "constructed type" syntax. It's documented here.
type-argument generic-type-name
or
generic-type-name
With the following examples:
int option
string list
int ref
option<int>
list<string>
ref<int>
Dictionary<int, string>
I was curious if there's anything special about the "backwards" syntax, with the parameter before the type, or if it's just sugar for generic types with one parameter. The following is valid:
type 'a MyOption = // MyOption<'a> also works
| MySome of 'a
| MyNone
But I could not get it to work with multiple type parameters. Why do F# developers prefer this syntax for types with one parameter? Is it possible or desirable to make it work with two?
The backwards syntax is a legacy from OCaml. Personally, I never use it. If you really want to, you can make it work with multiple type arguments like this:
type MyMap = (int, string) Map
However, this generates a pointed warning (that might soon become an error):
This construct is for ML compatibility. The syntax '(typ,...,typ) ident' is not used in F# code. Consider using 'ident<typ,...,typ>' instead. You can disable this warning by using '--mlcompatibility' or '--nowarn:62'.
Bottom line, I would recommend always using .NET syntax instead: MyOption<'a> instead of 'a MyOption.
Why do F# developers prefer this syntax for types with one parameter?
Not all of us do. I love F# and am in awe of it, but find the OCaml style distracting.
It gets especially confusing when the two styles are mixed - compare the readability of Async<Result<int,string list>> list with that of List<Async<Result<int,List<string>>>>.
Here is a thread with some arguments from both sides from fslang suggestions, which I think led to the deprecation of OCaml-style for everything but list, option and a few others.
I find it regrettable that the OCaml style is specified as the preferred option (for these types) in the various style guides, and used throughout the core libraries, while there is such a strong drive to make the language more accessible to newcomers. It definitely adds to the learning curve, as documented in this question,
and here,
here,
here,
here,
here.
Is it possible or desirable to make [OCaml style naming] work with two [type parameters]?
I think a better question is: "Is it possible to only use .NET style?".
Unfortunately the tooling shows types the way they are declared, and the core libraries consistently use OCaml style. I have asked Rider about always showing declarations .NET style in code vision, who referred me to FSharp compiler services. I have not (yet) investigated that avenue further.
In our own code we have taken to overriding the OCaml signatures of functions that ship with F# and other libraries as we come across them, for example:
[<AutoOpen>]
module NoCaml =
module List =
/// Returns a new collection containing only the elements of the collection for which the given predicate returns "true"
let filter = List.filter : ('a -> bool) -> List<'a> -> List<'a>
/// val groupBy : projection:('T -> 'Key) -> list:'T list -> ('Key * 'T list) list (requires equality and equality) 'T is 'a 'Key is 'b Applies a key-generating function to each element of a list and yields a list of unique keys. Each unique key contains a list of all elements that match to this key.
let groupBy = List.groupBy : ('a -> 'b) -> List<'a> -> List<'b * List<'a>>
// etc.
This solves the problem in almost all cases (some exceptions like list construction using [] remain, and need to be overridden at the point of declaration).
I'm not sure what influence this has on performance at runtime - hopefully the extra function calls are optimised away.
Related
I'm reading Elm documentation related to syntax, and stumbled upon this snippet:
type User
= Regular String Int
| Visitor String
what type Regular and Visitor is? another type that never defined before? or a function?
it does like a function call, but the parameter is a type, it doesn't look like function signature because there's no ->
This is documented in the relevant section of the Elm Guide (note that this is linked to from the section in the syntax guide that you link to in your question), but I admit it isn't quite as clear to a beginner as it should be.
Regular and Visitor are indeed functions, and not types, in your example. (In Haskell and PureScript they would be called "(data) constructors", which essentially can be used as regular functions but with the extra feature of being usable in pattern matching on the type they're defined in. Elm has quite a few differences from these 2 languages but has much the same roots, and indeed you can do pattern matching in this way in Elm too.)
This is proved by the REPL examples on the page I linked to, from which the following is a verbatim copy and paste:
> type User
| = Regular String Int
| | Visitor String
|
> Regular
<function> : String -> Int -> User
> Visitor
<function> : String -> User
And like all functions in Elm (again as in Haskell etc.) these functions are automatically curried, so in your example Regular "something" is a function of type Int -> User.
As you observe, "it doesn't look like a function signature" - and it's not. This isn't how you define a typical function. It's instead a definition of a custom data type, which then gives you these "constructor functions" for free.
The way that the "fast pipe" operator is compared to the "pipe last" in many places implies that they are drop-in replacements for each other. Want to send a value in as the last parameter to a function? Use pipe last (|>). Want to send it as the first parameter? Use fast pipe (once upon a time |., now deprecated in favour of ->).
So you'd be forgiven for thinking, as I did until earlier today, that the following code would get you the first match out of the regular expression match:
Js.String.match([%re "/(\\w+:)*(\\w+)/i"], "int:id")
|> Belt.Option.getExn
-> Array.get(1)
But you'd be wrong (again, as I was earlier today...)
Instead, the compiler emits the following warning:
We've found a bug for you!
OCaml preview 3:10-27
This has type:
'a option -> 'a
But somewhere wanted:
'b array
See this sandbox. What gives?
Looks like they screwed up the precedence of -> so that it's actually interpreted as
Js.String.match([%re "/(\\w+:)*(\\w+)/i"], "int:id")
|> (Belt.Option.getExn->Array.get(1));
With the operators inlined:
Array.get(Belt.Option.getExn, 1, Js.String.match([%re "/(\\w+:)*(\\w+)/i"], "int:id"));
or with the partial application more explicit, since Reason's syntax is a bit confusing with regards to currying:
let f = Array.get(Belt.Option.getExn, 1);
f(Js.String.match([%re "/(\\w+:)*(\\w+)/i"], "int:id"));
Replacing -> with |. works. As does replacing the |> with |..
I'd consider this a bug in Reason, but would in any case advise against using "fast pipe" at all since it invites a lot of confusion for very little benefit.
Also see this discussion on Github, which contains various workarounds. Leaving #glennsl's as the accepted answer because it describes the nature of the problem.
Update: there is also an article on Medium that goes into a lot of depth about the pros and cons of "data first" and "data last" specifically as it applies to Ocaml / Reason with Bucklescript.
I hope this question is appropriate for this site, it's just about the choice of concrete syntax in Idris compared to Haskell, since both are very similar. I guess it's not that important, but I'm very curious about it. Idris uses => for some cases where Haskell uses ->. So far I've seen that Idris only uses -> in function types and => for other things like lambdas and case _ of. Did this choice come from realizing that it's useful in practice to have a clear syntactical distinction between these use cases? Is it just an arbitrary cosmetic choice and I'm overthinking it?
Well, in Haskell, type signatures and values are in different namespaces, so something defined in one is at no risk of clashing with something in the other. In Idris, types and values occupy the same namespace, which is why you don't see e.g. data Foo = Foo as you would in Haskell, but rather, data Foo = MkFoo - the type is called Foo, and the constructor is called MkFoo, as there is already a value (the type Foo), bound to the name Foo, e.g. data Pair = MkPair http://docs.idris-lang.org/en/latest/tutorial/typesfuns.html#tuples
So it's probably for the best it didn't try to use the arrow used to construct the type of functions, with the arrow used for lambdas - those are rather different things. You can combine them with e.g. the (Int -> Int) (\x => x).
I think it is because they interpret the -> symbol differently.
From Wikipedia:
A => B means if A is true then B is also true; if A is false then nothing is said about B
which seems right for case expressions, and
-> may mean the same as =>, or it may have the meaning for functions given below
which is
f: X -> Y means the function f maps the set X into the set Y
So my guess is that Idris just uses -> for the narrow second meaning, i.e. for mapping one type to another in type signatures, whereas Haskell uses the broader interpretation, where it means the same as =>.
XCode 6: Beta 5:
Goal:
I am trying to write generic code for types that are semantically compatible but do not share (or appear to share) sufficient protocols to base my generics on a subset of shared protocols. So far, I have not been able to find a solution, and am wondering I am missing something or if it is a limitation of the language - any insight is appreciated.
Problem:
I have some functions that differ only by type and not by semantics and seem like a natural fit for generics. The problem that I am having, is that from what I can tell, Swift does what seems like parse-time binding of generics, failing if there could conceivably be a problem, and not when there actually is one.
Example:
Consider the following generic functions in a contrived example:
func defVal<T where T:FloatingPointType, T:FloatLiteralConvertible>(T.Type) -> T {
return 0.0
}
func defVal<T:IntegerLiteralConvertible>(T.Type) -> T {
return 0
}
Note that I have provided functions that should span the cases of integers and floats, and intentionally did not want to provide an exhaustive list of all possible variations that are of no relevance to me.
I then want to define generic code that spans types - in this example, int and float types. Note that this code fails to compile even in the absence of any code that calls it:
func doSomethingGeneric<T>(t:T) -> [T]
{
let a = defVal(T) // Type 'T' does not conform to protocol FloatLiteralConvertible
let b = a * a // works
return [t]
}
In my recollection, this would compile in C++ until you called it with an incompatible type, at which point the compiler would catch it.
I also tried other variants of diminished utility:
func doSomethingWithFloats<T
where T:FloatingPointType, T:FloatLiteralConvertible>(t:T) -> [T]
{
let a = defVal(T) // works
let b = a * a // T is not convertible to UInt8
// - need a floating point arithmetic type?
let c = -a // T is not convertible to Float
let f:Float = -a // T is not convertible to Float
return [t]
}
Given the sense that Swift provides protocols as a way of grouping concrete instances (specialized, not generic), I concocted a protocludge:
protocol Initializable {}
extension Float : Initializable {}
extension Double : Initializable {}
extension CGFloat : Initializable {}
func doSomethingWithInitializable<T:Initializable>(t:T) -> [T]
{
let a = defVal(T) // Type 'T' does not conform to protocol FloatLiteralConvertible
let b = a * a // works
return [t]
}
Note that this fails even though FloatLiteralConvertible is implemented across the set of all Initializable types. Put another way, Swift seems to be binding the generic types too early, and treating generic types as if they were specialized concrete instances instead of a greater pattern that would compile out further down the chain. Furthermore, note that while I could derive from FloatLiteralConvertible, this would preclude me from supporting int types etc. If there was a common ArithmeticType protocol, that could conceivably work, but I do not see anything of the sort. And this is the crux of the problem - there is no common protocol that works for both, even though both ints and floating types are semantically compatible (have the same rules of math).
So in summary, how do you write generic functions for which the types are semantically compatible, but for which there are not enough spanning protocols to filter by protocol (in this case - FloatingPointType does not implement IntegerArithmeticType, but is semantically capable of arithmetic).
Thanks in advance.
Unlike C++, Swift does not deal with generics by substituting the concrete types at the call site and making a non-generic copy (at least in general it doesn't - as an optimization that's allowed, but I digress)
Swift deals with genericity by passing in metadata information describing the actual types at each invocation into one master function, which then uses metadata-provided entry points to manipulate your objects
In your example, Initializable does not provide any operations, so when the compiler tries to execute defVal(T) it has no clue what to do (how can it ensure that there is an overload of defVal for your type?)
What you want to do is actually define defVal as a static function on the Initializable protocol, and then implement it in the extensions, then Swift will know that T.defVal() means something akin to
metadata[Initializable]->defVal(metadata)
Oh, since you're trying to execute a *(T,T), you might also want to make a Multipliable protocol and then your T will be typed as
<T: protocol<Initializable,Multipliable>>
in linq, .Where takes a Expression> predicate, which I can write in F# as
<# fun item:'a -> condition #> // Expr<'a -> bool>
I'm using FSharp.Powerpack to build the expression from a quotation, but what it gives me is a MethodCallExpression. Looking deep, the powerpack code builds the lambda correctly, but wraps it in a Convert call (why is that?). I wonder if casting the argument to the method call (a lambda) would finally give me the Expression> I need.
So the question is why the Convert call, and how to actually get the lambda with the Func signature.
I can't remember off the top of my head where I found this bit of code, but this is what I use to convert an Expr<'a -> 'b> to Expression<Func<'a, 'b>>. Hopefully this will solve your problem.
open System
open System.Linq.Expressions
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Linq.QuotationEvaluation
let toLinq (expr : Expr<'a -> 'b>) =
let linq = expr.ToLinqExpression()
let call = linq :?> MethodCallExpression
let lambda = call.Arguments.[0] :?> LambdaExpression
Expression.Lambda<Func<'a, 'b>>(lambda.Body, lambda.Parameters)
One way you can now do this is to take advantage of the fact that F# will perform this conversion automatically when invoking methods on .NET types that expect a Expression<Func<...>>.
I'm not entirely sure when this got added to the language, but certainly with F# 4, you don't need to explicitly convert F# expressions into LINQ ones. If the reason you wanted to do this in the first place was to be able to use IQueryable LINQ APIs (or other expression-based .NET APIs) then it now just works with no effort, e.g.:
someEfDataContext.MyEntities.Single(fun e -> e.Id = 42)
just works. Even though this looks like an ordinary lambda (we've not used F#'s expression syntax), this compiles to code that produces an F# expression object, and then passes that to LeafExpressionConverter.QuotationToExpression to turn it into a LINQ expression object.
But sometimes you'll want to get hold of the LINQ-style expression object directly in F#. (E.g., sometimes it's useful to write an F# function that produces an expression that you'll use in multiple queries.) In that case you can write a helper like this:
type FunAs() =
static member LinqExpression<'T, 'TResult>(e: Expression<Func<'T, 'TResult>>) = e
This looks like it does nothing - it just returns its argument. However, because FunAs is a .NET type, F# will automatically compile any call site that invokes this with a fun expression into code that generates a suitable LINQ query expression. E.g.:
let linqExpr = FunAs.LinqExpression(fun (e:MyEntity) -> e.Id = 42)
Here, linqExpr will be of type Expression<Func<MyEntity, bool>>.
The key to this is that this method is a member of a .NET Type. If you try the exact same thing with an ordinary F# function:
let funAsLinqExpression<'T, 'TResult>(e: Expression<Func<'T, 'TResult>>) = e
which seems like it should mean exactly the same thing as FunAs.LinqExpression, you'll find that you can't call it in the same way. E.g., if you try this:
let linqExpr = funAsLinqExpression(fun (e:MyEntity) -> e.Id = 42)
You'll get a (slightly unhelpful) error: 'This function takes too many arguments, or is used in a context where a function is not expected`.
By making this function a member of a .NET type, we can take advantage of F#'s helpful "You seem to be invoking a .NET API that expects a LINQ-style expression, let me take care of that for you" feature.
(It's possible that there's some more explicit way of asking the LINQ compiler to perform this same trick for you without bringing a .NET type into the picture, but I've not found it.)