4
votes

I am trying to have Name return the value of item.name where item is an instance of a C# class.

the fs file contains

namespace PatternMatch

type PatternMatch() = 
    member this.X = "F#"

namespace Items_

the fsx file contains

#load "PatternMatch.fs"
open PatternMatch

open Items_

type item = Item

let Name item = item.name //this line throws the error

let rec sentence s item  = function
    | s when s="Action" -> ""
    | s when s="Client" -> ""
    | s when s="Classifier" -> ""    
    | s when s="Container" -> ""    
    | s when s="ControlFlow" -> ""
    | s when s="Gaurd" -> ""
    | s when s="Name" -> Name item
    | s when s="ObjectFlow" -> ""    
    | s when s="Source" -> ""    
    | _ -> ""

let Name item = item.name throws the error. Items_ is a C# namespace and Item is a C# class within.

The entire error is:

Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved. C:\Users\jzbedocs\Local Files\Visual Studio 2010\Projects\addin\trunk\PatternMatch\Script.fsx 11 17 PatternMatch

1
You need a type annotation for item param of Name function. - Eugene Fotin
isn't the line type item = Item the annotation? Item is a c# class. - user3033411
@user3033411 type item = Item creates a type alias. In let Name (item: Item) = item.Name param item has a type annotation of Item. - Eugene Fotin

1 Answers

4
votes

let Name item = item.name has no type annotation. The parameter item is unconstrained other than by a member constraint which is not supported implicitly (see here for making it explicit -- don't do that...)

It looks like you got confused because the parameter name item is the same as the type alias item. If you want to explicitly make that so do this:

let Name (itemParameter:item) = itemParameter.name

I haven't checked if the parameter can have the same name as the alias, but it's probably a bad idea since it might be confused with the type parameter (we just saw this!).

Edit: Ok, I checked. You can have the parameter name be the same as the annotated type of the parameter, but it results in a horribly confusing type signature and implementation:

> let Name (item:item) = item.name;;

val Name : item:item -> string // EW!

If you're feeling particularly evil, you could even do something like this:

> let item (item:item) : item = item;;

val item : item:item -> item //Huh?

As an aside:

let rec sentence s item  = function
    | s when s="Action" -> ""
    | s when s="Client" -> ""
    | s when s="Classifier" -> ""    
    | s when s="Container" -> ""    
    | s when s="ControlFlow" -> ""
    | s when s="Gaurd" -> ""
    | s when s="Name" -> Name item
    | s when s="ObjectFlow" -> ""    
    | s when s="Source" -> ""    
    | _ -> ""

is probably better expressed as:

let rec sentence s item  = 
    match s with
    | "Action" -> ""
    | "Client" -> ""
    | "Classifier" -> ""    
    | "Container" -> ""    
    | "ControlFlow" -> ""
    | "Gaurd" -> "" //Guard maybe?
    | "Name" -> Name item
    | "ObjectFlow" -> ""    
    | "Source" -> ""    
    | _ -> ""

Here is a working example using a simple definition of Item (shown using the repl):

> type Item() =
    member val name = "" with get,set
type item = Item

let Name (itemParameter:item) = itemParameter.name

let test = item();;
test.name <- "test"
Name test;;

val it : string = "test"