This runtime coercion or type test from type 'a to Ellipse

Answered This runtime coercion or type test from type 'a to Ellipse

  • Tuesday, April 03, 2012 9:56 AM
     
      Has Code

    This runtime coercion or type test from type 'a to Ellipse    
    involves an indeterminate type based on information prior to this program point.
    Runtime type tests are not allowed on some types. Further type annotations are needed.

    open System
    open System.IO
    open System.Net
    open System.Net.Sockets
    open System.Text
    open System.Threading
    open System.Collections.Generic
    open System.Collections
    open Microsoft.FSharp.Collections 
    open System.Drawing
    open System.Windows.Forms
    open System.Collections.Generic
    open System.Windows
    open System.Windows.Controls
    open System.Windows.Markup
    open System.Configuration
    open System.Data
    open System.Data.SqlClient
    open System.Configuration
    open System.Windows.Media
    open System.Windows.Media.Imaging
    open System.Collections.ObjectModel
    open System.Windows.Shapes
    open System.Runtime.Serialization 
    open System.Runtime.Serialization.Formatters.Binary
    open System.Security.Cryptography
    open System.Linq
    open System.Reflection
    open System.Xml
    open System.Xml.Linq
    [<AttributeUsage(AttributeTargets.Field, AllowMultiple = false)>]
    type UiElementAttribute(name : string) =     
        inherit System.Attribute()   
        new() = new UiElementAttribute(null)    
        member this.Name = name 
        
    [<AbstractClass>]type FsUiObject<'T when 'T :> FrameworkElement> (xamlPath) as this =     
        let loadXaml () =        
            use stream = System.IO.File.OpenRead(xamlPath)        
            System.Windows.Markup.XamlReader.Load(stream)    
        let uiObj = loadXaml() :?> 'T         
        let flags = System.Reflection.BindingFlags.Instance ||| System.Reflection.BindingFlags.NonPublic ||| System.Reflection.BindingFlags.Public         
        do         
            let fields =             
                this.GetType().GetFields(flags)             
                |> Seq.choose(fun f ->                 
                    let attrs =  f.GetCustomAttributes(typeof<UiElementAttribute>, false)                
                    if attrs.Length = 0 then 
                        None                
                    else                    
                        let attr = attrs.[0] :?> UiElementAttribute                    
                        Some(f, if String.IsNullOrEmpty(attr.Name) then f.Name else attr.Name)                
                )        
            for field, name in fields do            
                let value = uiObj.FindName(name)            
                if value <> null then                
                    field.SetValue(this, value)            
                else                
                    failwithf "Ui element %s not found" name     
        member x.UiObject = uiObj 
     
    let _random = new Random()
    let Damping = 0.95
    let Gravity = 0.7;
    let Resistance = 0.995
    let TotalBalls = 2
    (*
            AY : double,
            AX : double,
            X : double,
            Y : double,
            OldX : double,
            OldY : double
    *)
    type PhysicsInfo() =
        member g.AY with get() = AY and set(value) = AY <- value
        member g.AX with get() = AX and set(value) = AX <- value
        member g.X with get() = X and set(value) = X <- value
        member g.Y with get() = Y and set(value) = Y <- value
        member g.OldX with get() = OldX and set(value) = OldX <- value
        member g.OldY with get() = OldY and set(value) = OldY <- value
        
    let InitPhysicsForBall : PhysicsInfo= 
        let p = new PhysicsInfo()
        //_random.NextDouble() * ActualWidth,
        //_random.NextDouble() * ActualHeight,
        p.AY = _random.NextDouble() * 600.0
        p.AX = _random.NextDouble() * 480.0
        p.X = _random.NextDouble() * 10.0
        p.Y =_random.NextDouble() * 10.0
        p.OldX = 0.0,
        p.OldY = 0.0
        //)
        p
    let CreateBalls(win : FsUiObject<Window>) = 
        for i = 0 to TotalBalls-1 do 
            let e : Ellipse = new Ellipse()
            e.Width <- 20.0
            e.Height <- 20.0
            
            let _container = win.UiObject.FindName("_container") :?> Canvas
            _container.Children.Add(e)
            let info = InitPhysicsForBall
            e.Tag <- info
    let SetConstraints(win : FsUiObject<Window>, ball : Ellipse, info : PhysicsInfo) =
        let _container = win.UiObject.FindName("_container") :?> Canvas
        let bounds : Size = _container.RenderSize
        if info.X <= 0.0 then
            info.X <- 0.0
            info.AX <- info.AX * -1.0 * Damping
        else if info.X >= bounds.Width - ball.Width then
            info.X <- bounds.Width - ball.Width
            info.AX <- info.AX * (-1.0) * Damping
        if info.Y <= 0.0 then
            info.Y <- 0.0
            info.AY <- info.AY*(-1.0) * Damping
        else if info.Y >= (bounds.Height - ball.Height) then
            info.Y <- bounds.Height - ball.Height
            info.AY <- info.AY*(-1.0) * Damping
    let UpdateBall(win : FsUiObject<Window>, info : PhysicsInfo) =
        info.AX = info.AX* Resistance
        info.AY = info.AY + Gravity
        info.AY = info.AY * Resistance
        info.X = info.X + info.AX
        info.Y = info.Y + info.AY
        
    let CompositionTarget_Rendering(win : FsUiObject<Window>) =
        let _container = win.UiObject.FindName("_container") :?> Canvas
        for i = 0 to TotalBalls-1 do 
            let ball : Ellipse = _container.Children[i] :?> Ellipse  <--- Error
            let info : PhysicsInfo = ball.Tag :?> PhysicsInfo
            UpdateBall(win, info)
            SetConstraints(win, ball, info)
            ball.SetValue(Canvas.LeftProperty, info.X)
            ball.SetValue(Canvas.TopProperty, info.Y)
            
    let Window1_Loaded(win : FsUiObject<Window>) = 
        CreateBalls
        CompositionTarget.Rendering += CompositionTarget_Rendering(win);
    type MainWindow() as this =
        inherit FsUiObject<Window>(Path.Combine(__SOURCE_DIRECTORY__, "Window.xaml"))
        
    [<System.STAThread()>]
    do
        let window = new MainWindow()
        window.UiObject.Loaded += Window1_Loaded(window)
        window.UiObject.ShowDialog() |> ignore 

    • Edited by 沈世鈞 Tuesday, April 03, 2012 9:57 AM
    •  

All Replies

  • Tuesday, April 03, 2012 12:38 PM
     
     
    Sorry, it's really hard to parse huge listings. But if compiler cannot infer some type here then the easiest way is to add a type annotation for the type in question

    Petr

  • Tuesday, April 03, 2012 8:05 PM
    Moderator
     
     Answered

    _container.Children[i] :?> Ellipse 

    should be

    _container.Children.[i] :?> Ellipse 

    array indexing in F# needs a dot


    Brian McNamara [MSFT]

    • Marked As Answer by 沈世鈞 Thursday, April 05, 2012 2:07 AM
    •