But I think this is really not possible. The type ?? is int32 or float32 or float.

There is no generic type.

It sounds like you may be trying to do is something that F# works very hard to prevent: storing and accessing data in an unconstrained polymorphic, but ultimately non-deterministically way.

F# containers by design only hold a single, constrained, monomorphic type of data. The idea is that rather than storing something of type "Object", one should rather define a specific set of types that the container can hold. In this way, the compiler can statically type check the container and help prevent one type of runtime error.

One could, for example, force a container to hold values of the Object type. In this case, one could put anything at all in the container, including boxed primitives such as an arbitrary mix of ints, float32, and doubles. However, the code would then need to attempt to determine the actual element types at run time, and every such case would also need to remember to handle exceptions when an unexpected type is encountered. Bear in mind that nothing would prevent one from adding, say, a string to such a container that normally expects numbers. Take the following example, which throws an exception at runtime:

1
2
3
4
5
6
7
8
9
10
11
12
13
#light
module badcode =

    let dump xs =
        let aux (x:obj) =
            match x with
            | :? int32 as x -> printfn "%i" x
            | :? float32 as i -> printfn "%f" i
            | :? double as d -> printfn "%f" d
            | _ -> failwithf "Unexpected type %s" ( x.GetType().ToString() )
        List.iter aux xs

    dump [ (1 :> obj); (3.1415f :> obj); (1.234 :> obj); ("abc" :> obj) ]

On the other hand, idiomatic F# code constrains the values in a container to a specific, and very deterministic set of types. Because of this, the compiler can flag cases where the code is not handling every potential type of data or, conversely, prevent addition of unacceptable types to such a container to begin with. For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#light
module safecode =

    type Number =
        | Int of int
        | Float of float32
        | Double of double

    let incompleteDump xs =
        let aux = function
//                ^^^^^^^^
//--> warning FS0025: Incomplete pattern matches on this expression. For example, the value 'Double (_)' will not be matched
            | Int(x)    -> printfn "%i" x
            | Float(f)  -> printfn "%f" f
        List.iter aux xs

    let dump xs =
        let aux = function
            | Int(x)    -> printfn "%i" x
            | Float(f)  -> printfn "%f" f
            | Double(d) -> printfn "%f" d
        List.iter aux xs 

    dump [ Int(1); Float(3.1415f); Double(1.234); "Abc" ]
//                                                ^^^^^
//--> error FS0001: This expression has type 'string' but is here used with type 'Number'

Therefore, the type system, language, and compiler conspire together to drive your code towards correctness. As an added benefit, the compiler can often infer types more easily. For example, the type passed to "aux" can be inferred.

By on 12/15/2008 1:40 AM ()

my naive attempt :

1
2
3
4
5
6
7
type number =
  |Nat of int32
  |Real of float32
  
type my_data =
  { data: number[]; dims: int list;status: int}
By on 12/8/2008 4:14 PM ()

Not really.

The idea is good. But it does not work with my code.

Thanks

By on 12/8/2008 4:57 PM ()

sounds like you want the covariant/contravariant feature which I believe is not supported in f#, may be in some future version.

By on 12/8/2008 6:18 PM ()

Why not

1
2
   type 'a nc_data =
       {data: 'a []; dims: int list; status: int;}

? Sure this will allow you to theoretically define nc_data types other than for float or int, but that's the whole point of automatic generalization. You don't ever have to use nc_data with any other type if you don't want.

By on 12/8/2008 7:53 PM ()

That is not what I want because
Is not possible write

let test x =
match x with
| 1 -> (new int32 nc_data ...)
| 2 -> (new float32 nc_data ...)
| 3 -> (new double nc_data ... )
| _ -> failwith " ... "

But this is a good idea for shrink my code.

By on 12/13/2008 5:23 AM ()

what about this ?

1
2
3
4
5
6
7
8
9
10
11
12
type nc_int_data = {data: int []; dims: int list; status: int;}
type nc_float_data = {data: float []; dims: int list; status: int;}
type nc_data =
   |Nc_int_data of nc_int_data
   |Nc_float_data of nc_float_data
 
let test x =
  match x with
  |1 -> Nc_int_data({data=[|1;2;3|];dims=[1;2;3];status=1})
  |2 -> Nc_float_data({data=[|1.0;2.0;3.0|];dims=[1;2;3];status=1})
  |_ -> failwith "hello"
By on 12/13/2008 9:04 PM ()

the problem now is: how do you get data values?

with
> let t2 = test 2;;
val tt : nc_data

> t2;;
val it : nc_data = Nc_float_data {data = [|1.0; 2.0; 3.0|];
dims = [1; 2; 3];
status = 1;}

If now I would get «data»

> t2.data;;
t2.data;;
^^^^^^
stdin(12,1): error FS0193: Type constraint mismatch. The type
nc_data is
not compatible with type
nc_float_data.
The type 'nc_data' is not compatible with the type 'nc_float_data'.

I test also with :
type nc_int_data = {data: int []; dims: int list; status: int;}
with
member x.values = x.data
end

type nc_float_data = {data: float []; dims: int list; status: int;}
with
member x.values = x.data
end

By on 12/14/2008 5:03 AM ()

Hello, jonaas.

There was similar threads, here is links to some:
[link:cs.hubfs.net]
[link:cs.hubfs.net]

In short, you can use:
- inline functions to simulate generics
- wrap your operations to abstract type
- active patterns
- OO mechanics

By on 12/14/2008 7:26 AM ()

[link:blog.matthewdoig.com]

pattern matching can extract the content and work on it but cannot return the content without using the trick in the above link

1
2
3
4
5
6
let d = test 2 
let y d = 
  match d with
  | Nc_int_data(i) -> i.data |> box
  | Nc_float_data(i) -> i.data |> box
By on 12/14/2008 6:21 AM ()

Thank you.
Functional programming is sometimes very complicated.

By on 12/14/2008 7:02 AM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper