1

I want to write a function that creates an object from a data stream, e.g.

let nxL<'T  when 'T : (new : unit -> 'T)> (sr:StreamReader) = 
    let line = sr.ReadLine()
    if line <> null then 
        Some(new 'T(line))
    else
        None

However, this doesn't work as it fails with:

Calls to object constructors on typed parameters cannot be given arguments.

Since a constructor is a function and F# is a functional language this makes no sense to me. Does anyone know how to create a function that takes a type as an argument and returns new instances?

evolvedmicrobe
  • 2,672
  • 2
  • 22
  • 30
  • 2
    It's not possible to specify generic constraint for parameterized constructor. And that's not just F#, that's .NET in general. – MarcinJuraszek May 17 '14 at 21:37
  • Further discussion of this here: http://stackoverflow.com/questions/7067214/why-c-sharp-dont-accept-constructor-requirements-with-parameters-on-generics – evolvedmicrobe May 17 '14 at 21:59
  • 1
    @MarcinJuraszek: Actually, [it is possible](http://stackoverflow.com/a/23745949/162396) in F#. – Daniel May 19 '14 at 19:44

2 Answers2

2

Although passing a function, as @scrwtp suggested, is a good aproach, what you want is possible:

let inline nxL (sr:StreamReader) = 
    let line = sr.ReadLine()
    if line <> null then 
        Some(^a : (new : string -> ^a) line)
    else
        None
Daniel
  • 47,404
  • 11
  • 101
  • 179
0

You could create an object given a type using Activator.CreateInstance, but I don't feel it's strictly necessary from the code snippet you posted. Wouldn't passing a regular function that takes a string and returns an object of the desired type work for you? Sort of a factory function, if you care. Like this:

let nxL<'T> (cons: string -> 'T) (sr:StreamReader) : 'T option = 
    let line = sr.ReadLine()
    if line <> null then 
        Some (cons line)
    else
        None

What's more, you could actually drop all the type annotations on it apart from StreamReader, and it will be inferred to be generic (leaving them on so it's clear what goes on in the snippet).

scrwtp
  • 13,437
  • 2
  • 26
  • 30
  • indeed, this was my work around, it was just a bit annoying having a function whose sole purpose is to wrap the constructor. – evolvedmicrobe May 17 '14 at 22:01
  • 1
    I guess it's part of F# having to fit into the existing .NET ecosystem. Interestingly, discriminated union case constructors are 'regular' functions in that regard, so you could use `SomeUnion.SomeCase` directly there. – scrwtp May 17 '14 at 22:08