键入提供程序在f#中为我提供“Unsuported Constant Type:System.double”错误

时间:2012-04-15 11:03:23

标签: f# type-providers

我想知道这个错误来自哪里。 这是代码,在TP下面,使用fsahrpx DSL

更新:我找到了一个“解决方案”,即在外面进行施法,并为每个施法者构建一个吸气剂。 如果有人知道为什么会这样,或者有更好的解决方案,我会很高兴知道。 (在ProvideTypes-0.2.fs中有限的报价模式?)

编辑:我绝望的失败尝试并不那么有趣。例如,两个有趣的是Test93,或Test92。为什么他们会失败?

更新 增加了最具诉讼性的案件90,91,92,93

module Module =
   open System.Reflection
   open Samples.FSharp.ProvidedTypes
   open FSharpx.TypeProviders.DSL
   open Microsoft.FSharp.Core.CompilerServices

   type ReflectiveBuilder = static member Cast<'a> (args:obj) = args :?> 'a
      static member BuildTypedCast lType (args: obj) = 
            typeof<ReflectiveBuilder>
               .GetMethod("Cast")
               .MakeGenericMethod([|lType|])
               .Invoke(null, [|args|])

   let bbgReference ns =
       erasedType<obj> (Assembly.GetExecutingAssembly()) ns "Reference"
       |> staticParameter "file"
          (fun typeName (parameterValues:string) ->
               let otwo = 2.0 :> obj
               let dtwo = 2.0 
               let dotwo = otwo :?> float

               let dcast = ReflectiveBuilder.BuildTypedCast typeof<float>

               let getter = match otwo with
                              | :? double as d -> (fun args -> <@@ d @@>)
                              | :? string as d -> (fun args -> <@@ d @@>)

               erasedType<string> (Assembly.GetExecutingAssembly()) ns typeName
           |+!> (   provideProperty 
                       "test90"                             //KO
                       (typeof<obj>)                   
                       (fun args -> <@@  otwo  @@>)     
                 )
           |+!> (   provideProperty 
                       "test91"                             //KO
                       (otwo.GetType())                  
                       (fun args -> <@@  otwo  @@>)     
                 )
           |+!> (   provideProperty 
                       "test92"                             //KO
                       (otwo.GetType())                  
                       (fun args -> <@@  otwo  @@>)     
                 )
           |+!> (   provideProperty 
                       "test93"                              //NO
                       typeof<float>                   
                       (fun args -> <@@  otwo :?> float  @@>)     
                 )

               |+!> (   provideProperty 
                           "test"                             //OK
                           typeof<float>                   
                           (fun args -> <@@  dtwo  @@>)      
                     )
               |+!> (   provideProperty 
                           "test2"                              //NO
                           typeof<float>                   
                           (fun args -> <@@  dtwo :> obj @@>)     
                     )
               |+!> (   provideProperty 
                           "test3"                              //NO
                           typeof<float>                   
                           (fun args -> <@@  otwo  @@>)     
                     )
               |+!> (   provideProperty 
                           "test4"                              //NO
                           typeof<float>                   
                           (fun args -> <@@  otwo :?> float  @@>)     
                     )
               |+!> (   provideProperty 
                           "test5"                              //OK
                           typeof<float>                   
                           (fun args -> <@@  dotwo  @@>)     
                     )
               |+!> (   provideProperty 
                           "test6"                              //OK
                           typeof<float>                   
                           (fun args -> <@@  dotwo :> obj  @@>)     
                     )
               |+!> (   provideProperty 
                           "test7"                              //NO
                           typeof<float>                   
                           (fun args -> <@@  dcast otwo  @@>)     
                     )
               |+!> (   provideProperty 
                           "test8"                              //OK
                           typeof<float>                   
                           getter    
                     )
               |+!> (provideConstructor
                        []
                        (fun _ -> <@@ "I will be the internal representation" @@>)))


   [<TypeProvider>]
   type public CustomTypeProvider(cfg:TypeProviderConfig) as this =
      inherit TypeProviderForNamespaces()

      do this.AddNamespace("TEST", [bbgReference "TEST"])

   [<TypeProviderAssembly>]
   do()

测试

module Program =
   open System

   type t = TEST.Reference<"">
   let price = t().Test90
   let price = t().Test91
   let price = t().Test92
   let price = t().Test93
   let price = t().Test    //OK
   let price = t().Test2   //OK
   let price = t().Test3   //NO OK
   let price = t().Test4   //NO OK
   let price = t().Test5   //OK
   let price = t().Test6   //OK
   let price = t().Test7   //NO OK
   let price = t().Test8   //OK

2 个答案:

答案 0 :(得分:3)

可以出现在F#类型提供程序的属性和方法的引用代码中的表达式非常有限 - 在编写类型提供程序时遇到了同样的问题。我认为目前没有精确的规范,因此找出答案的唯一方法是查看源代码或进行实验。

原因是为IL编译F#引用尚未在任何地方完全实现,因此类型提供程序的代码生成器可能只是实现了足以使其工作的基本功能。

在编写提供程序时,我通常遵循一种模式,其中所有“运行时”代码都放在一个模块中,并且传递给方法或属性的引用代码只调用此运行时。这是有效的,因为引用只是一个方法调用。类似的东西:

module CultureRuntime =
  let getCulture (name:string) = 
    // The runtime can contain arbitrary complex F# code
    CultureInfo.GetCultureInfo(name)

在向提供商添加适当内容时,报价只会调用CultureRuntime.getCulture

for culture in CultureInfo.GetCultures(CultureTypes.AllCultures) do
  let id = culture.Name
  ProvidedProperty
    ( culture.DisplayName, typeof<CultureInfo>, IsStatic = true,
      GetterCode = fun args -> <@@ CultureRuntime.getCulture id @@>)
  |> sampleTy.AddMember

编辑:我不太熟悉类型提供程序的代码生成如何在内部工作,但是您发现令人惊讶的情况几乎总是与<@ otwo @>或类似工具一起使用,其中{ {1}}类型为otwo

当类型提供程序从引号生成代码时,它需要为表达式System.Object生成IL代码。但是,这一般没有意义,因为如果otwo的类型为otwo,那么就无法生成重新创建对象的IL(或以其他方式序列化对象)。

出于这个原因,F#类型提供程序机制(可能)只允许可以轻松转换为IL的原始值(例如System.Object示例中类型float的值)。

答案 1 :(得分:2)

我们计划在未来几周内在示例codeplex网站上发布对ProvideTypes API的更新/修订。这个问题也将得到解决。