I'd like to create a type with a definition a bit like this:
type LeftRight<'left, 'right> = {
Left : 'left list
Right : 'right list
}
and a couple of functions:
let makeLeft xs = { Left = xs; Right = [] }
let makeRight ys = { Left = []; Right = ys }
and I'd like to provide a 'combiner' function:
let combine l r = { Left = l.Left # r.Left; Right = l.Right # r.Right }
When I try and make something, I (obviously!) get issues as my value is generic:
let aaa = makeLeft [1;2;3]
// Value restriction. The value 'aaa' has been inferred to have generic type
// val aaa : LeftRight<int,'_a>
If I combine a left and a right, type inference kicks in and everything's A-OK:
let bbb = makeRight [1.0;2.0;3.0]
let comb = combine aaa bbb // LeftRight<int, float>
but I want to use one with only lefts on its own. I tried creating an 'Any' type:
type Any = Any
and explicitly specified the types on makeLeft and makeRight:
let makeLeft xs : LeftRight<_, Any> = { Left = xs; Right = [] }
let makeRight ys : LeftRight<Any, _> = { Left = []; Right = ys }
which makes the value definitions happy, but makes the combine function sad:
let combined = combine aaa bbb
// Type mismatch. Expecting a
// LeftRight<int,Any>
// but given a
// LeftRight<Any,float>
// The type 'int' does not match the type 'Any'
I feel like there's probably a way around this with loads of voodoo with .Net's overloading of function calls, but I can't make it work. Has anyone tried this before/have any ideas?
The value restriction is not a problem in this case, you need the result of makeLeft or makeRight be generic if you ever hope to use them generically further down the line.
In F# (and OCaml), generic syntactic values must be explicitly marked as such, with full type annotations. Indeed, the compiler reports this:
error FS0030: Value restriction. The value 'aaa' has been inferred to
have generic type
val aaa : LeftRight Either define 'aaa' as a simple data term, make it a function with explicit arguments or, if you do
not intend for it to be generic, add a type annotation.
Without going into too much detail*, this is to avoid issues that can occur when combining polymorphism and side effects. The downside is that it does reject some perfectly safe code as a result.
So, the solution is simple, we make these values explicitly generic:
let aaa<'a> : LeftRight<int,'a> = makeLeft [1;2;3]
let bbb<'a> : LeftRight<'a, float> = makeRight [1.0;2.0;3.0]
Putting them together in FSI:
let comb = combine aaa bbb;;;
val comb : LeftRight<int,float> = {Left = [1; 2; 3];
Right = [1.0; 2.0; 3.0];}
Note that if you combine without intermediate let bindings, you no longer have a generic value and the proper type can be inferred by the compiler:
combine (makeLeft [1;2;3]) (makeRight [1.0;2.0;3.0]);;
val it : LeftRight<int,float> = {Left = [1; 2; 3];
Right = [1.0; 2.0; 3.0];}
*For more detail, check out this article.
Related
I have a data pipeline where at each step more data fields are required. I would like to do this in a functional way by respecting immutability. I could achieve this with a class by I am wondering if there is an F# way of doing it?
// code that loads initial field information and returns record A
type recordA = {
A: int
}
// code that loads additional field information and returns record AB
type recordAB = {
A: int
B: int
}
// code that loads additional field information and returns record ABC
type recordABC = {
A: int
B: int
C: int
}
As records are sealed I can't just inherit them. How can I avoid having to define a new record with the exact same fields as the previous step and adding the required fields? Preferably I would like to have something like one record that has all required fields and the fields get assigned to their values in each step.
Note that the number of fields added in each step could be more than 1.
I think this can be a good use case for the anonymous records recently introduced in F#.
let a = {| X = 3 |}
let b = {| a with Y = "1"; Z = 4.0|}
let c = {| b with W = 1 |}
printfn "%d, %s, %f, %d" c.X c.Y c.Z c.W
One way to do it in a very FP-style would be to use a DU with a case for each step of the workflow, and the appropriate data for each step in each case:
type WorfklowState =
| StepOne of int
| StepTwo of int * int
| StepThree of int * int * int
Then your entire workflow state, both what step you're currently on and the data produced/consumed by that step, would be modeled in the data type. Of course, you would probably create record types for the data of each case, rather than using progressively larger tuples.
Depending on the application, this may be a (mis-)use case for a dynamic data container.
F# might help by providing user-defined dynamic lookup operators, for which a special syntactic translation occurs.
let (?) (m : Map<_,_>) k = m.Item k
// val ( ? ) : m:Map<'a,'b> -> k:'a -> 'b when 'a : comparison
let (?<-) (m : Map<_,_>) k v = m.Add(k, v)
// val ( ?<- ) : m:Map<'a,'b> -> k:'a -> v:'b -> Map<'a,'b> when 'a : comparison
let m = Map.empty<_,_>
let ma = m?A <- "0"
let mabc = (ma?B <- "1")?C <- "2"
ma?A // val it : string = "0"
mabc?C // val it : string = "2"
You can "inherit" records:
type RecordA =
{
a : int
}
type RecordAB =
{
a : RecordA
b : int
}
type RecordABC =
{
ab : RecordAB
c : int
}
Then you can access all of the elements, though with longer and longer chain as you go deeper and deeper.
However, why don't you just use a list of elements to store the result?
First, I would create a type to handle all possible types that you may have on each step, e.g.:
type Step =
| Int of int
| String of string
// ...
Then you can represent the workflow simply as:
type WorkflowState = list<Step>
and if you want to ensure that you always have at least one element then you can use:
type WorkflowState = Step * list<Step>
However, the records have labels and the structure above does not have them! So, if you do need labels, then you can represent them by a map using either a strong type:
type Label =
| A
| B
// ...
type WorkflowMappedState = Map<Label, Step>
or just a string based one, e.g.
type WorkflowMappedState = Map<string, Step>
The benefits of list or map based approach in comparison to the answers above is that you don't have to know the maximum number of possible steps. What if the number of steps is over 100? Would you want to create a record with 100+ labels? Most likely not! The anonymous records are great, but what if you want to use them outside of module where they were created? I think that that would cause some troubles.
Having said all that, I think that I would go with a list based approach: type WorkflowState = list<Step>. It is very F# way and it is very easy to transform further.
Is it possible to express something like this:
type id = int > 0
I know its not possible to do statically, since this would mean F# has dependent types. In C# I'm used to do this sort of thing with code contracts and get a runtime enforcement. I'm looking for something similiar here.
Thanks
EDIT:
Thank you for all the answers which have various pros and cons. At the monent I'm only using a small subset of F#, a subset of the ocaml core that lends itself easily to program proofs. So no classes.
Contrary to what others said, I would suggest not using classes here, if I understood your problem correctly.
Since the value is immutable, we need applying constraint only once. Any wrapper classes would be an overhead and load GC. Instead, a simple function will do the job:
let inline constrained predicate errormessage value =
if not (predicate value)
then invalidArg "value" errormessage
else value
let positive =
constrained (fun x -> x > 0) "Value must be positive"
let int1 = positive 5 // OK
let int2 = positive -3 // ArgumentException
You can do the same for other types:
let mustBeLong =
constrained (fun (x:string) -> x.Length > 3) "String must be long"
let str1 = mustBeLong "foobar" // OK
let str2 = mustBeLong "baz" // ArgumentException
Using the same within a struct:
type Point2D =
struct
val X: int
val Y: int
new(x: int, y: int) = { X = positive x; Y = positive y }
end
let point1 = Point2D(5, 3) // OK
let point2 = Point2D(5, -2) // ArgumentException
Define it as a union type:
type Id = Id of int
and shadow the constructor with another function:
let Id n =
assert(n > 0)
Id n
In F#, you have to resort to classes and check arguments inside constructors. Other types such as discriminated unions, records and structs have implicit constructors which you can't easily alter.
type Id(i: int) =
do if i <= 0 then
invalidArg "i" "the argument has to be a positive integer"
member x.Value = i
Pattern matching doesn't play nicely with classes. You can remedy the problem using active patterns:
let (|Id|) (id: Id) = id.Value
let id = Id(1)
match id with
| Id 1 -> printfn "matched"
| _ -> printfn "unmatched"
You could create a generic class like so:
type verify<'t>(t:'t,cond) =
let mutable tval = t
let _verify v = if not (cond v) then failwith "bad argument"
do _verify tval
member x.get() = tval
member x.set v =
_verify v
tval <- v
then you can use it with
verify(1,fun t -> t>0)
using .set will recheck the condition.
I'm reading Expert F# book and I found this code
open System.Collections.Generic
let divideIntoEquivalenceClasses keyf seq =
// The dictionary to hold the equivalence classes
let dict = new Dictionary<'key,ResizeArray<'T>>()
// Build the groupings
seq |> Seq.iter (fun v ->
let key = keyf v
let ok,prev = dict.TryGetValue(key)
if ok then prev.Add(v)
else let prev = new ResizeArray<'T>()
dict.[key] <- prev
prev.Add(v))
dict |> Seq.map (fun group -> group.Key, Seq.readonly group.Value)
and the example use:
> divideIntoEquivalenceClasses (fun n -> n % 3) [ 0 .. 10 ];;
val it : seq<int * seq<int>>
= seq [(0, seq [0; 3; 6; 9]); (1, seq [1; 4; 7; 10]); (2, seq [2; 5; 8])]
first for me this code is really ugly, even if this is safe, It looks more similar to imperative languages than to functional lang..specially compared to clojure. But the problem is not this...I'm having problems with the Dictionary definition
when I type this:
let dict = new Dictionary<'key,ResizeArray<'T>>();;
I get this:
pruebafs2a.fs(32,5): error FS0030: Value restriction. The value 'dict' has been inferred to have generic type
val dict : Dictionary<'_key,ResizeArray<'_T>> when '_key : equality
Either define 'dict' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation.
is It ok?...
thanks so much
improve question:
Ok I've been reading about value restriction and I found this helpfull information
In particular, only function definitions and simple immutable data
expressions are automatically generalized
...ok..this explains why
let dict = new Dictionary<'key,ResizeArray<'T>>();;
doesn't work...and show 4 different techniques, although in my opinion they only resolve the error but aren't solutions for use generic code:
Technique 1: Constrain Values to Be Nongeneric
let empties : int list [] = Array.create 100 []
Technique 3: Add Dummy Arguments to Generic Functions When Necessary
let empties () = Array.create 100 []
let intEmpties : int list [] = empties()
Technique 4: Add Explicit Type Arguments When Necessary (similar to tec 3)
let emptyLists = Seq.init 100 (fun _ -> [])
> emptyLists<int>;;
val it : seq<int list> = seq [[]; []; []; []; ...]
----- and the only one than let me use real generic code ------
Technique 2: Ensure Generic Functions Have Explicit Arguments
let mapFirst = List.map fst //doesn't work
let mapFirst inp = List.map fst inp
Ok, in 3 of 4 techniques I need resolve the generic code before can work with this...now...returning to book example...when the compile knows the value for 'key and 'T
let dict = new Dictionary<'key,ResizeArray<'T>>()
in the scope the code is very generic for let key be any type, the same happen with 'T
and the biggest dummy question is :
when I enclose the code in a function (technique 3):
let empties = Array.create 100 [] //doesn't work
let empties () = Array.create 100 []
val empties : unit -> 'a list []
I need define the type before begin use it
let intEmpties : int list [] = empties()
for me (admittedly I'm a little dummy with static type languages) this is not real generic because it can't infer the type when I use it, I need define the type and then pass values (not define its type based in the passed values) exist other way define type without be so explicit..
thanks so much..really appreciate any help
This line
let dict = new Dictionary<'key,ResizeArray<'T>>();;
fails because when you type the ;; the compiler doesn't know what 'key and 'T are. As the error message states you need to add a type annotation, or allow the compiler to infer the type by using it later or make it a function
Examples
Type annotation change
let dict = new Dictionary<int,ResizeArray<int>>();;
Using types later
let dict = new Dictionary<'key,ResizeArray<'T>>()
dict.[1] <- 2
using a function
let dict() = new Dictionary<'key,ResizeArray<'T>>();;
This actually doesn't cause an issue when it's defined all together. That is, select the entire block that you posted and send it to FSI in one go. I get this:
val divideIntoEquivalenceClasses :
('T -> 'key) -> seq<'T> -> seq<'key * seq<'T>> when 'key : equality
However, if you type these individually into FSI then as John Palmer says there is not enough information in that isolated line for the interpreter to determine the type constraints. John's suggestions will work, but the original code is doing it correctly - defining the variable and using it in the same scope so that the types can be inferred.
for me this code is really ugly, even if this is safe, It looks more similar to imperative languages than to functional lang.
I agree completely – it's slightly tangential to your direct question, but I think a more idiomatic (functional) approach would be:
let divideIntoEquivalenceClasses keyf seq =
(System.Collections.Generic.Dictionary(), seq)
||> Seq.fold (fun dict v ->
let key = keyf v
match dict.TryGetValue key with
| false, _ -> dict.Add (key, ResizeArray(Seq.singleton v))
| _, prev -> prev.Add v
dict)
|> Seq.map (function KeyValue (k, v) -> k, Seq.readonly v)
This allows sufficient type inference to obviate the need for your question in the first place.
The workarounds proposed by the other answers are all good. Just to clarify based on your latest updates, let's consider two blocks of code:
let empties = Array.create 100 []
as opposed to:
let empties = Array.create 100 []
empties.[0] <- [1]
In the second case, the compiler can infer that empties : int list [], because we are inserting an int list into the array in the second line, which constrains the element type.
It sounds like you'd like the compiler to infer a generic value empties : 'a list [] in the first case, but this would be unsound. Consider what would happen if the compiler did that and we then entered the following two lines in another batch:
empties.[0] <- [1] // treat 'a list [] as int list []
List.iter (printfn "%s") empties.[0] // treat 'a list [] as string list []
Each of these lines unifies the generic type parameter 'a with a different concrete type (int and string). Either of these unifications is fine in isolation, but they are incompatible with each other and would result in treating the int value 1 inserted by the first line as a string when the second line is executed, which is clearly a violation of type safety.
Contrast this with an empty list, which really is generic:
let empty = []
Then in this case, the compiler does infer empty : 'a list, because it's safe to treat empty as a list of different types in different locations in your code without ever impacting type safety:
let l1 : int list = empty
let l2 : string list = empty
let l3 = 'a' :: empty
In the case where you make empties the return value of a generic function:
let empties() = Array.create 100 []
it is again safe to infer a generic type, since if we try our problematic scenario from before:
empties().[0] <- [1]
List.iter (printfn "%s") (empties().[0])
we are creating a new array on each line, so the types can be different without breaking the type system.
Hopefully this helps explain the reasons behind the limitation a bit more.
Is there a way to have mutable function arguments in F#, that would allow something like
let mutable i = 9
let somefun n = n <- 12; ()
somefun i
(* *not* a real-world example *)
I do understand that this can be made to work by wrapping it into a record type
type SomeRec = { mutable i: int }
let ri = { i = 9 }
let someotherfun r = r.i <- 12; ()
and that this can be done in a similar fashion for class members. However, even after browsing through the whole F# Language Specification (yes, I did!), there seems to be no syntax to allow the first case, and the compiler appears to be quite unhappy about my trying this. I was hoping there would be some sort of type annotation, but mutable cannot be used in such.
I also know that I should not be doing this sort of thing in the first place, but the first case (int binding) and the second (record type) are semantically identical, and any such objection would hold for both cases equally.
So I think that I am missing something here.
You can use ref as arguments
let v = ref 0
let mutate r =
r := 100
mutate v
printfn "%d" !v
Or byref keyword
let mutable v = 0
let mutate (r : byref<_>) =
r <- 100
mutate &v
printfn "%d" v
Use byref keyword which is equivalent to C# ref.
See Passing by reference.
Is it just me, or does F# not cater for cyclic lists?
I looked at the FSharpList<T> class via reflector, and noticed, that neither the 'structural equals' or the length methods check for cycles. I can only guess if 2 such primitive functions does not check, that most list functions would not do this either.
If cyclic lists are not supported, why is that?
Thanks
PS: Am I even looking at the right list class?
There are many different lists/collection types in F#.
F# list type. As Chris said, you cannot initialize a recursive value of this type, because the type is not lazy and not mutable (Immutability means that you have to create it at once and the fact that it's not lazy means that you can't use F# recursive values using let rec). As ssp said, you could use Reflection to hack it, but that's probably a case that we don't want to discuss.
Another type is seq (which is actually IEnumerable) or the LazyList type from PowerPack. These are lazy, so you can use let rec to create a cyclic value. However, (as far as I know) none of the functions working with them take cyclic lists into account - if you create a cyclic list, it simply means that you're creating an infinite list, so the result of (e.g.) map will be a potentially infinite list.
Here is an example for LazyList type:
#r "FSharp.PowerPack.dll"
// Valid use of value recursion
let rec ones = LazyList.consDelayed 1 (fun () -> ones)
Seq.take 5 l // Gives [1; 1; 1; 1; 1]
The question is what data types can you define yourself. Chris shows a mutable list and if you write operations that modify it, they will affect the entire list (if you interpret it as an infinite data structure).
You can also define a lazy (potentionally cyclic) data type and implement operations that handle cycles, so when you create a cyclic list and project it into another list, it will create cyclic list as a result (and not a potentionally infinite data structure).
The type declaration may look like this (I'm using object type, so that we can use reference equality when checking for cycles):
type CyclicListValue<'a> =
Nil | Cons of 'a * Lazy<CyclicList<'a>>
and CyclicList<'a>(value:CyclicListValue<'a>) =
member x.Value = value
The following map function handles cycles - if you give it a cyclic list, it will return a newly created list with the same cyclic structure:
let map f (cl:CyclicList<_>) =
// 'start' is the first element of the list (used for cycle checking)
// 'l' is the list we're processing
// 'lazyRes' is a function that returns the first cell of the resulting list
// (which is not available on the first call, but can be accessed
// later, because the list is constructed lazily)
let rec mapAux start (l:CyclicList<_>) lazyRes =
match l.Value with
| Nil -> new CyclicList<_>(Nil)
| Cons(v, rest) when rest.Value = start -> lazyRes()
| Cons(v, rest) ->
let value = Cons(f v, lazy mapAux start rest.Value lazyRes)
new CyclicList<_>(value)
let rec res = mapAux cl cl (fun () -> res)
res
The F# list type is essentially a linked list, where each node has a 'next'. This in theory would allow you to create cycles. However, F# lists are immutable. So you could never 'make' this cycle by mutation, you would have to do it at construction time. (Since you couldn't update the last node to loop around to the front.)
You could write this to do it, however the compiler specifically prevents it:
let rec x = 1 :: 2 :: 3 :: x;;
let rec x = 1 :: 2 :: 3 :: x;;
------------------------^^
stdin(1,25): error FS0260: Recursive values cannot appear directly as a construction of the type 'List`1' within a recursive binding. This feature has been removed from the F# language. Consider using a record instead.
If you do want to create a cycle, you could do the following:
> type CustomListNode = { Value : int; mutable Next : CustomListNode option };;
type CustomListNode =
{Value: int;
mutable Next: CustomListNode option;}
> let head = { Value = 1; Next = None };;
val head : CustomListNode = {Value = 1;
Next = null;}
> let head2 = { Value = 2; Next = Some(head) } ;;
val head2 : CustomListNode = {Value = 2;
Next = Some {Value = 1;
Next = null;};}
> head.Next <- Some(head2);;
val it : unit = ()
> head;;
val it : CustomListNode = {Value = 1;
Next = Some {Value = 2;
Next = Some ...;};}
The answer is same for all languages with tail-call optimization support and first-class functions (function types) support: it's so easy to emulate cyclic structures.
let rec x = seq { yield 1; yield! x};;
It's simplest way to emulate that structure by using laziness of seq.
Of course you can hack list representation as described here.
As was said before, your problem here is that the list type is immutable, and for a list to be cyclic you'd have to have it stick itself into its last element, so that doesn't work. You can use sequences, of course.
If you have an existing list and want to create an infinite sequence on top of it that cycles through the list's elements, here's how you could do it:
let round_robin lst =
let rec inner_rr l =
seq {
match l with
| [] ->
yield! inner_rr lst
| h::t ->
yield h
yield! inner_rr t
}
if lst.IsEmpty then Seq.empty else inner_rr []
let listcycler_sequence = round_robin [1;2;3;4;5;6]