by this code
module ObjectRe =
type BM = A | N
type Object = {
Name: string
Pattern: BM array
}
let patterns = [|{Name = "Pro"; Pattern = [|A;N;N;A|]} |]
I always get this error message
System.TypeLoadException: Could not load type 'FSI_0007+ObjectRe+Object[]' from assembly 'FSI-ASSEMBLY, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&)
at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00038] in <94fd79a3b7144c54b4cb162b50fc7761>:0
Stopped due to error
Has anyone an idea? I use Visual Studio Code on Mac.
Thanks
I can also reproduce this on macOS 10.11, mono 4.6.
The minimal reproduction is :
module X =
type Y = Y
let l = [| Y |]
With a workaround :
module X =
type Y = Y
let g = List.toArray [ Y ]
So in your case replace both the inner and the outer [| |] declarations.
Why this happens only in VS Code/fsharpi but not in Xamarin?
If you fire up activity monitor you will see that VS Code/fsharpi uses the
/Library/Frameworks/Mono.framework/Versions/4.6.0/lib/mono/4.5/fsi.exe binary, but Xamarin Studio uses the FCS Xamarin Studio.app/Contents/Resources/lib/monodevelop/AddIns/BackendBindings/MonoDevelop.FSharpInteractive.Service.exe You can check also the version on the first message from the interactive (F# Interactive for F# 4.1, those might be different).
Finally, i believe this is a bug on mono + dynamic assemblies, triggered by the code emitted by the fsi. Compiling this code to an exe works fine on all platforms (and if you check the generated IL seems pretty normal).
Related
Why does my version of the Elmish.WPF Sample NewWindow (XAML code and F# Core) emit the error ...
The type 'unit -> 'a' is not compatible with the type 'Window'.
The same line emits the warning...
This construct causes code to be less generic than indicated by its type annotations. The type variable implied by the use of a '#', '_' or other type annotation at or near <line reference to createWindow_Window2 in the let bindings = statement">
Why am I getting this error and warning?
What I am doing is merging the Elmish.WPF Samples SingleCounter (XAML code and F# Core) and NewWindow (XAML code and F# Core) to have the Model, bindings(), and Msg parts in Program.fs instead of App.fs (as it was in the NewWindow sample).
My goal is to make a SimpleCounter able to open a NewWindow.
The XAML code passes Func<Window2> into the F# code here...
let main mainWindow (createWindow2: Func<#Window>)
...I define bindings as...
let bindings = Platform.bindings createWindow_Window2
I am down to the one compiler error I mentioned above (and that also appears in line beginning "let bindings = ..." below)...
let main mainWindow (createWindow_Window2: Func<#Window>) =
let logger =
LoggerConfiguration()
.MinimumLevel.Override("Elmish.WPF.Update", Events.LogEventLevel.Verbose)
.MinimumLevel.Override("Elmish.WPF.Bindings", Events.LogEventLevel.Verbose)
.MinimumLevel.Override("Elmish.WPF.Performance", Events.LogEventLevel.Verbose)
.WriteTo.Console()
.CreateLogger()
let createWindow_Window2 =
let window = createWindow_Window2.Invoke()
window.Owner <- mainWindow
window
let bindings = Platform.bindings createWindow_Window2
WpfProgram.mkProgramWithCmdMsg (fun _ -> m_init, []) update bindings toCmd
|> WpfProgram.withLogger (new SerilogLoggerFactory(logger))
|> WpfProgram.startElmishLoop mainWindow
The top of Program.bindings is defined as ...
let bindings (createWindow_Window2: unit -> #Window) () : Binding<Model, Msg> list = [
"Window_Window2_Show|> Binding.cmd Window_AboutProduct_Show
"Window_Window2" |> Binding.subModelWin(
Window_Window2.get >> WindowState.ofOption,
snd,
Window_Window2ct.mapInOutMsg,
Window_Window2_Module.Window_Window2.bindings,
createWindow_Window2,
isModal = true)
...bindings continue but are not relevant to this question...
... and reports no errors!
The compiler seems to think Platform.bindings is expecting unit -> `a when createWindow_Window2 is correctly typed as unit -> #Window.
You can see the call into Program.fs:main is correctly called from App.xaml.cs with a lambda function returning a Window2 as follows...
private void StartElmish(object sender, EventArgs e)
{
this.Activated -= StartElmish;
Program.main(MainWindow, () => new Window2());
}
So my question is why am I getting this mismatch type error when it seems I am passing the correct types?
Thank you!
I think one issue in your code is that the name createWindow_Window2 is used both as the name of an argument of main, but then later also as a local variable in the function of differnt type. Another issue is that in one place, you try to use a delegate type Func<#Window> but in another place, you have an ordinary F# function Window -> unit.
My advice would be to use Window -> unit everywhere and avoid variable shadowing:
let main mainWindow (createWindow_Window2:Window -> unit) = (* Changed type here *)
let logger = (* omitted *)
let createWindowWithOwner () =
(* Renamed and added '()' so that it is a function *)
let window = createWindow_Window2 () (* Just function call *)
window.Owner <- mainWindow
window
let bindings =
Platform.bindings createWindowWithOwner (* Pass the right function here *)
(* omitted *)
A big thank you to: Brian Berns, Bent Tranberg, and Tomas Petricek for helping me!
The answer to my problem was astonishingly simple to an expert but to a relative novice only yielded after meticulous comparison with the working Elmish.WPF code for NewWindow.
For easy comparison I have pushed up to rfreytag/Elmish.WPF a version of the NewWindow (XAML code and F# Core) sample that compiles and runs (REMEMBER to build the NewWindow sample).
This version of NewWindow (XAML code and F# Core) when compiled shows the error and warning I reported above …
The type 'unit -> 'a' is not compatible with the type 'Window'.
See also C:\Workspace\Elmish.WPF\src\Samples\AnotherNewWindow.Core\Program.fs(78,72)-(78,79).
...and the warning...
This construct causes code to be less generic than indicated by its
type annotations. The type variable implied by the use of a '#', '_'
or other type annotation at or near
'C:\Workspace\Elmish.WPF\src\Samples\AnotherNewWindow.Core\Program.fs(78,72)-(78,79)'
has been constrained to be type 'unit -> 'a'.
To see the precise fix you can compare the working and breaking branches on my copy of Elmish.WPF. Which is that I had forgotten the () following the definition of let createWindow_Window2 = ...
let createWindow_Window2 =
let window = createWindow_Window2.Invoke()
window.Owner <- mainWindow
window
... returns the function () -> Window while the correct ...
let createWindow_Window2 () =
let window = createWindow_Window2.Invoke()
window.Owner <- mainWindow
window
... returns the needed Window.
A newbie looks at unit → ‘a and doesn’t immediately recognize it as a function. And of course, functions are not C# Window objects.
Did not help me that the error message doesn’t follow the F# form of...
expecting a <type sought by context>
but was given a <passed in type>
...which has become familiar from working with the F# compiler.
Not sure why this message diverged from that pattern. Maybe someone can explain that?
The warning is alerting to the less-specific #Window (see # ‘flexible type’ definition) possibly clashing at run-time with the unit → ‘a function.
As usual, learning a new framework means learning the compiler and linker messages.
By referencing the default WPF DLLs, it's pretty easy to do anything you could do using code-only WPF:
#r "PresentationCore.dll"
#r "PresentationFramework.dll"
// ...other DLLs...
#r "WindowsBase.dll"
let window = System.Windows.Window()
let panel = System.Windows.Controls.StackPanel()
let button = System.Windows.Controls.Button()
panel.Children.Add button
button.Content <- "hi"
window.Content <- panel
window.Show()
... and you can manipulate it while the window is still open...
button.Click.Add (fun _ ->
button.Content <-
button.Content :?> string |> fun x -> (x + "!") :> obj)
...and then click the button to see it work. It seems like a pretty powerful way to build up UI components.
Is there any way to do the same thing with the Windows.UI namespace/controls/UI framework -- load some assemblies in F# interactive and instantiate UI components on the fly?
I've naively tried referencing the files that seemed relevant:
#r #"C:\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.UniversalApiContract\2.0.0.0\Windows.Foundation.UniversalApiContract.winmd"
#r #"C:\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.FoundationContract\2.0.0.0\Windows.Foundation.FoundationContract.winmd"
...and doing that gets me intellisense into the Windows.UI namespaces. But when I try to instantiate something:
Windows.UI.Xaml.Application()
I get:
error FS0193: Could not load file or assembly 'file:///C:\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.UniversalApiContract\2.0.0.0\Windows.Foundation.UniversalApiContract.winmd' or one of its dependencies. Operation is not supported. (Exception from HRESULT: 0x80131515)
There is no compiler support for WinRT assemblies, so you're not going to be able to reference an assembly as you're attempting to do and use the types in them cleanly.
On the other hand... since the .NET runtime has native support for WinRT types, you can use reflection to load those types and access their members. With a lot of effort, you could even build a type provider to provide a clean façade over that reflection and make it appear as though you can use the types directly. Here's a small example of how to directly call a WinRT API from F# via reflection:
open System.Reflection
let (?) (o:obj) s : 'a =
let rec build ty args =
if Reflection.FSharpType.IsFunction ty then
let dom, rng = Reflection.FSharpType.GetFunctionElements ty
let mkArgs =
if dom = typeof<unit> then
if Reflection.FSharpType.IsFunction rng then failwith "Unit as non-final argument in curried definition?"
fun _ -> args
else
fun arg -> arg::args
Reflection.FSharpValue.MakeFunction(ty, fun o -> build rng (mkArgs o))
else
let rcvr,ty,flags =
match o with
| :? System.Type as ty -> null,ty,BindingFlags.Static
| _ -> o,o.GetType(),BindingFlags.Instance
let flags = flags ||| BindingFlags.Public
let meth =
if Reflection.FSharpType.IsFunction typeof<'a> then
query {
for m in ty.GetMethods(flags) do
where (m.Name = s)
where (m.GetParameters().Length = args.Length)
exactlyOne
}
else
ty.GetProperty(s, flags).GetGetMethod()
meth.Invoke(rcvr, args |> List.toArray)
build typeof<'a> [] :?> 'a
let Clipboard = System.Type.GetType(#"Windows.ApplicationModel.DataTransfer.Clipboard, Windows.ApplicationModel, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime")
Clipboard?GetContent()?AvailableFormats |> Seq.iter (printfn "%s")
My understanding is that there is no F# support for UWP yet.
See for instance this fresh open issue.
It's trying to make a TypeProvider for Xamarin.Forms, but has been plagued by FS2024 error.
Parse own library from the XAML of Xamarin.Forms
Assign x:Name to Propertis
`F#
type MainPage = Moonmile.XamarinFormsTypeProvider.XAML<"MainPage.xaml">
// made btn1 and text1 propertis
type MainPageEx(target:MainPage) =
let mutable count = 0
do
// When set event to btn.Clicked, happen FS2024 error.
// If this event is comment out, it success build.
target.btn1.Clicked.Add( fun e ->
count <- count + 1
target.btn1.Text <- "Clicked " + count.ToString())
// Property is success
member this.CurrentPage
with get() = target.CurrentPage
When you are referring to a property, build & operation you can normally.
But the internal class of Xamarin.Forms like Button.Clicked, If you try to access to, it is the build error.
Sample code for error
https://github.com/moonmile/SimpleEventTypeProvider
Making code for XamarinFormsTypeProvider
github.com/moonmile/XamarinFormsTypeProvider
Maybe, I suspect inconsistencies and is happening in the part of the generation of a Native TypeProvider and Xamrin.Forms.Core a PCL.
F# Compiler for F# 3.1 (Open Source Edition)
Freely distributed under the Apache 2.0 Open Source License my error!!!
isMscorlib: true
name: "System.Runtime"
PrimaryAssembly.DotNetCore.Name: "System.Runtime"
PrimaryAssembly.Mscorlib.Name: "mscorlib"
parameter error FS2024: Static linking may not use assembly that targets different profile.
It's to operate the property they work properly, and to MVVM perhaps.
Butt I am trying to implement a way to be assigned to Button.Clicked events
as shown in the codebehide-like buildings if possible.
Would there workaround or what?
In the case of XAML in WPF, How can such seems to work well.
github.com/fsprojects/FsXaml
This answer isn't guaranteed to be correct, but it should help at least point you in the right direction.
The first thing to do is to make sure that you have installed the latest Visual F# Tools Build, as this adds the FSharp.Core that is compatible with the PCL profiles (You can find it here: (https://visualfsharp.codeplex.com/). Once that is installed, you will want to reference either the Profile78, or Profile259 FSharp.Core.dll (On my machine, these are found at: "C:\Program Files (x86)\Reference Assemblies\Microsoft\FSharp.NETPortable\2.3.5.0", and "C:\Program Files (x86)\Reference Assemblies\Microsoft\FSharp.NETPortable\2.3.5.1" respectively).
Once you have that installed, the next thing to do is make sure that your PCL projects have the following in their project files (This tells MSBuild / xBuild that the projects are PCL libraries, and that they are F# Projects):
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{F2A71F9B-5D33-465A-A702-920D77279786}</ProjectTypeGuids>
Once that is done, you will need to select either Profile78, or Profile259 (I would recommend 78, as the current Xamarin.Forms nuget package doesn't support 259).
Once that is done, then you should be able to build and run and it should get rid of the error.
Thank you for my question.
Meybe,
When it build TypeProvider, F# compiler use classes in mscorlib.
When it resolve the type of btn1.Clicked event, the F# comiler use type in System.Runtime.
I think for that, and it can not be resolved at build time
Try, if you attach the Clicked Event using reflection, it has moved successfully on Android build through.
I seem, if it I use only shard classes in mscorlib and System.Rutime, I can build no FS2024 error.
type MainPage = Moonmile.XamarinFormsTypeProvider.XAML<"MainPage.xaml">
type MainPageEx() as this =
inherit BindObject<MainPage>(new MainPage())
// Add handlder by reflection
let AddHandler(target:obj, eventName:string, eventMethod: obj*obj -> unit ) =
let hdr = Action<obj,obj>( fun s e -> eventMethod(s,e))
let ei = target.GetType().GetRuntimeEvent(eventName)
let dt = ei.AddMethod.GetParameters().[0].ParameterType
let handler = new Action<obj,obj>(fun s e -> hdr.Invoke( s, new EventArgs() ))
let handlerInvoke = handler.GetType().GetRuntimeMethod("Invoke", [|typeof<obj>; typeof<Type[]>|])
let dele = handlerInvoke.CreateDelegate( dt, handler )
let add = new Func<Delegate, EventRegistrationToken> ( fun t ->
let para = ei.AddMethod.GetParameters()
let ret = ei.AddMethod.Invoke( target, [|t|])
if ret <> null then
ret :?> EventRegistrationToken
else
new EventRegistrationToken()
)
let remove = new Action<EventRegistrationToken>( fun t -> ei.RemoveMethod.Invoke(target, [|t|]) |> ignore )
// WindowsRuntimeMarshal.AddEventHandler<Delegate>(add, remove, dele)
add.Invoke( dele ) |> ignore
()
let mutable count = 0
do
(* // build error
target.btn1.Clicked.Add( fun e ->
count <- count + 1
target.btn1.Text <- "Clicked " + count.ToString())
*)
// add handler by reflection
AddHandler( base.Target.btn1, "Clicked", this.ButtonClick )
()
member this.CurrentPage
with get() = this.Target.CurrentPage
member this.ButtonClick(s,e) =
count <- count + 1
base.Target.text1.Text <- "clicked " + count.ToString()
I'm having a hard time deciphering the "Providing Generated Types" section of the Type Provider Tutorial. The tutorial provides the following specification.
"You must also call ConvertToGenerated on a root provided type whose nested types form a closed set of generated types. This call emits the given provided type definition and its nested type definitions into an assembly and adjusts the Assembly property of all provided type definitions to return that assembly. The assembly is emitted only when the Assembly property on the root type is accessed for the first time. The host F# compiler does access this property when it processes a generative type declaration for the type."
I do not know where to place the ConvertToGenerated call and I'm not sure on the requirements of the assembly file name parameter. Can someone provide an example? Thanks.
After some help from the F# team I solved my problem. This is what I did.
namespace Types
open System
open System.Data
open System.IO
open System.Linq
open System.Data.Linq
open Microsoft.FSharp.Data.TypeProviders
open Microsoft.FSharp.Linq
open Microsoft.FSharp.TypeProvider.Emit
open Microsoft.FSharp.Core.CompilerServices
type DatabaseSchema =
SqlDataConnection<"Data Source=(local);Initial Catalog=Test;Integrated Security=SSPI;">
[<TypeProvider>]
type public MeasureTypeProvider(cfg:TypeProviderConfig) as this =
inherit TypeProviderForNamespaces()
let assembly = System.Reflection.Assembly.GetExecutingAssembly()
let typesNamespace = "Types.Domain"
let providedTypeBuilder = ProvidedTypeBuilder.Default
let db = DatabaseSchema.GetDataContext()
let types =
query { for m in db.Table do select m }
|> Seq.map(fun dataEntity ->
let className:string = dataEntity.Identifier
let providedTypeDefinition =
ProvidedTypeDefinition(className = className,
baseType = Some typeof<obj>,
IsErased=false)
providedTypeDefinition.AddMember(
ProvidedConstructor([], InvokeCode = fun [] -> <## obj() ##>))
providedTypeDefinition
) |> Seq.toList
let rootType =
let providedTypeDefinition =
ProvidedTypeDefinition(assembly,
typeNamespace,
"DomainTypes",
Some typeof<obj>,
IsErased=false)
providedTypeDefinition.AddMembersDelayed(fun () -> types)
this.AddNamespace(typesNamespace, [providedTypeDefinition])
providedTypeDefinition
let path = Path.GetDirectoryName(assembly.Location) + #"\GeneratedTypes.dll"
do rootMeasureType.ConvertToGenerated(path)
[<assembly:TypeProviderAssembly>]
do()
The TypeProvider.Emit framework automatically cleans up the generated assembly. Comment out the following statement if you want it to stick around.
File.Delete assemblyFileName
One other gotcha I found is that while I was able to provide types that derive from value types (like decimal) when IsErased=true, I was not able to provide these derived types when IsErased=false. This is because value types are sealed so it is is not possible to generate a "real" type that derives from a value type.
I'm trying to create an AppDomain and attach to its UnhandledException event from F#, and I'm not having much luck. In my event handler I need a reference to the domain that fired the event, as well as the event arguments.
To reproduce this issue, the following code must be run in a compiled application. Running it in F# Interactive produces a different, probably-not-related error.
open System
open System.Reflection
let domainError (domain:AppDomain) (args:UnhandledExceptionEventArgs) =
()
let domain = AppDomain.CreateDomain("test")
domain.UnhandledException
|> Event.add (domainError domain)
This compiles just fine, but at runtime I get the following error:
SerializationException: Type 'Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers+h#720' in assembly 'FSharp.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' is not marked as serializable.
The stack trace that goes along with this error is as follows:
at System.AppDomain.add_UnhandledException(UnhandledExceptionEventHandler value)
at Program.clo#9.Invoke(UnhandledExceptionEventHandler eventDelegate) in c:\users\joel\documents\visual studio 2010\Projects\EventTest\Program.fs:line 9
at Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers.CreateEvent#716.Subscribe(IObserver`1 observer)
at Microsoft.FSharp.Control.CommonExtensions.SubscribeToObservable[T](IObservable`1 x, FSharpFunc`2 callback)
at Microsoft.FSharp.Control.EventModule.Add[T,TDel](FSharpFunc`2 callback, IEvent`2 sourceEvent)
at <StartupCode$EventTest>.$Program.main#() in c:\users\joel\documents\visual studio 2010\Projects\EventTest\Program.fs:line 9
Now I obviously can't make Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers+h#720 serializable, so can anyone suggest a workable way of attaching to this particular event? Thanks for any suggestions.
Update
Thanks to a suggestion from ChaosPandion, this version works:
open System
open System.Reflection
let domainError (sender:obj) (args:UnhandledExceptionEventArgs) =
let problemDomain = sender :?> AppDomain
printfn "Unhandled exception in app domain: %s" problemDomain.FriendlyName
()
let domain = AppDomain.CreateDomain("test")
domain.UnhandledException.AddHandler(UnhandledExceptionEventHandler(domainError))
After a bit more tweaking I found this example will fail:
let domainError (domain:AppDomain) =
let handler (sender:obj) (e:UnhandledExceptionEventArgs) =
let msg = (e.ExceptionObject :?> Exception).Message
printfn "An exception was unhandled in %s\nMessage:%s" domain.FriendlyName msg
new UnhandledExceptionEventHandler(handler)
let main() =
let domain = AppDomain.CreateDomain("test")
let handler = domainError domain
domain.UnhandledException.AddHandler handler
I broke open Reflector and found the root cause. (Which is actually quite obvious now that I think about it.)
internal class handler#28 : OptimizedClosures.FSharpFunc<object, UnhandledExceptionEventArgs, Unit>
{
// Fields
public AppDomain domain;
// Methods
internal handler#28(AppDomain domain);
public override Unit Invoke(object sender, UnhandledExceptionEventArgs e);
}
This pretty much means that the only way you can get this to work is to not create the closure around the domain object. I am not sure if this will work for you but you may want to try using the following from within the handler.
AppDomain.CurrentDomain