f# parsing string to color - parsing

type circle = { X : int; Y : int; Diameter : int; Color : Color}
let mutable clickedCircle = { X = 0; Y = 0; Diameter = 0; Color = Color.White}
let txtBoxVal4 = System.Enum.Parse(typeof<Color>,txtBox2.Text)
clickedCircle <- {X = txtBoxVal2; Y = txtBoxVal3; Diameter = txtBoxVal1; Color = txtBoxVal4}
I am trying to parse a textbox.text into a color. From this code i get the error:
Error 1 This expression was expected to have type
Color
but here has type
obj
Quite new to F# and not to sure about the syntax. The error comes at
"Color = txtBoxVal4"

System.Enum.Parse returns an obj type that you need to cast to the enum type. You can do that using :?> or downcast. In your case the type is known so you can use downcast.
See the Casting and Conversions docs for more.
clickedCircle <- {X = txtBoxVal2; Y = txtBoxVal3; Diameter = txtBoxVal1; Color = downcast txtBoxVal4}

A wrapper function for Enum.Parse could make good use of the enum constraint and eliminate the need for unboxing at the call site.
module Enum =
let parse<'T, 'U when 'T : enum<'U>> value = Enum.Parse(typeof<'T>, value) :?> 'T
let color = Enum.parse "Black"

Related

DRY self-replicating type

Is there a succint way to express self-replicating types in F#? — That is, without repeating oneself.
// Manual self-replication
type Foo (par1 : Type1, par2 : Type2, par3 : Type3, par4 : Type4) =
let unique = new UniqueState() // unique for every instance of Foo
member this.SelfReplicate =
new Foo(par1, par2, par3, par4) // repeating myself
let a = new Foo(x, y, z, w)
let b = a.SelfReplicate
Attempt with manually injected self-replicator:
// Semi-automagic self-replication
type Foo' (par1 : Type1, par2 : Type2, par3 : Type3, par4 : Type4, replicate : unit -> Foo') =
let unique = new UniqueState() // unique for every instance of Foo'
member this.SelfReplicate = replicate() // not repeating myself
let rec foo' () = new Foo'(x, y, z, w, foo')
let a = foo'()
let b = a.SelfReplicate
I'm not sure how this can be any more succint without compiler magic. It just seems like there should be a way to capture the current arguments and type without repeating them syntactically.
You could define a type WithUnique<'T> which is a wrapper over a value of type 'T and adds a unique value to this. You may need to think about how you want the equality testing on those types to work - if you use record (as I do below), then two instances with different unique value will not be equal:
let rnd = System.Random()
let uniqueState() = rnd.Next()
type WithUnique<'T> =
{ Value : 'T; Unique : int }
static member Create(v) : WithUnique<'T> =
{ Value = v; Unique = uniqueState() }
member x.Replicate() =
{ Value = x.Value; Unique = uniqueState() }
The value of 'T is just one type, but this can be a tuple (or a record) if you need to wrap multiple things:
let wu1 = WithUnique.Create( (10, "hi") )
let wu2 = wu1.Replicate()
Given the above, wu1=wu2 will be false.

The pattern discriminator is not defined

I'm new in F#, can you help me with this error: 'The pattern discriminator is not defined'
let findColorIndex colorArray, color =
let mutable index=0
for i in 0..colorArray.Length-1 do
if Color.FromName(colorArray.[i]).R.Equals(color.R) then
if Color.FromName(colorArray.[i]).G.Equals(color.G) then
if Color.FromName(colorArray.[i]).B.Equals(color.B)
then index<-i
index
The error message is difficult to read. It is the initial comma that the compiler does not like. You probably mean either
let findColorIndex colorArray color =
or
let findColorIndex (colorArray, color) =
Stylistically, your code looks like a straight translation of C# code. It works but it doesn't look very nice. I rewrote it as follows:
// A little helper function to get all color values at once
let getRGB (color : Color) = (color.R, color.G, color.B)
let findColorIndex colorArray color =
let rec findIdx i =
// If no matching color is found, return -1
// Could use options instead...
if i >= colorArray.Length then -1
elif getRGB (Color.FromName colorArray.[i]) = getRGB color then i
else findIdx (i + 1)
findIdx 0
Alternatively you could use Array.tryFindIndex:
let findColorIndex colorArray color =
// Returns None if no matching index is found,
// otherwise Some index
colorArray |> Array.tryFindIndex (fun c ->
getRGB (Color.FromName c) = getRGB color)

FSCL error on a simple example

I am trying to use openCL with FSCL on F# but I am obtaining some errors that I don't understand
open FSCL.Compiler
open FSCL.Language
open FSCL.Runtime
open Microsoft.FSharp.Linq.RuntimeHelpers
open System.Runtime.InteropServices
[<StructLayout(LayoutKind.Sequential)>]
type gpu_point2 =
struct
val mutable x: float32
val mutable y: float32
new ( q ,w) = {x=q; y=w}
end
[<ReflectedDefinition>]
let PointSum(a:gpu_point2,b:gpu_point2) =
let sx =(a.x+b.x)
let sy =(a.y+b.y)
gpu_point2(sx,sy)
[<ReflectedDefinition;Kernel>]
let Modgpu(b:float32[], c:float32[],wi:WorkItemInfo) =
let gid = wi.GlobalID(0)
let arp = Array.zeroCreate<gpu_point2> b.Length
let newpoint = gpu_point2(b.[gid],c.[gid])
arp.[gid] <- newpoint
arp
[<ReflectedDefinition;Kernel>]
let ModSum(a:gpu_point2[],b:gpu_point2[],wi:WorkItemInfo) =
let gid = wi.GlobalID(0)
let cadd = Array.zeroCreate<gpu_point2> a.Length
let newsum = PointSum(a.[gid],b.[gid])
cadd.[gid] <- newsum
cadd
[<ReflectedDefinition;Kernel>]
let ModSum2(a:gpu_point2[],b:gpu_point2[],wi:WorkItemInfo) =
let gid = wi.GlobalID(0)
let cadd = Array.zeroCreate<gpu_point2> a.Length
let newsum = gpu_point2(a.[gid].x+b.[gid].x,a.[gid].y+b.[gid].y)
cadd.[gid] <- newsum
cadd
let ws = WorkSize(64L)
let arr_s1= <# Modgpu([|0.f..63.f|],[|63.f..(-1.f)..0.f|],ws)#>.Run()
let arr_s2 = <# Modgpu([|63.f..(-1.f)..0.f|],[|0.f..63.f|],ws)#>.Run()
With this code when I try to use ModSum as
let rsum = <# ModSum(arr_s1,arr_s2,ws)#>.Run()
doesn't work, but instead when I use ModSum2 works perfectly
let rsum = <# ModSum2(arr_s1,arr_s2,ws)#>.Run()
The error I obtain the first time I run it is
FSCL.Compiler.CompilerException: Unrecognized construct in kernel body NewObject (gpu_point2, sx, sy)
and if I re-run the fsi console says
System.NullReferenceException: Object reference not set to an instance of an object.
The only thing I know is that the error doesn't comes from the use of another function since I can define a dot product function that works.
[<ReflectedDefinition>]
let PointProd(a:gpu_point2,b:gpu_point2) =
let f = (a.x*b.x)
let s = (a.y*b.y)
f+s
Thus, I guess the problem comes from the return type of PointSum, but is there a way to create such a function to sum two points and return the point type? And Why is not working?
Edit/Update:
Also with a record happens the same if I define the type as :
[<StructLayout(LayoutKind.Sequential)>]
type gpu_point_2 = {x:float32; y:float32}
If I try to create a function that directly sums two gpu_point_2 on a function works, but if I call a second function it raises the same error as using a struct.
Try to add [<ReflectedDefinition>] on the constructor of gpu_point2:
[<StructLayout(LayoutKind.Sequential)>]
type gpu_point2 =
struct
val mutable x: float32
val mutable y: float32
[<ReflectedDefinition>] new (q, w) = {x=q; y=w}
end
Normally each code that is called from the device need this attribute, constructors included.

Is it possible to force record type in F# when doing an assignment?

To explain I think it is best with an example:
type myRec = {x: string}
type myRec2 = {x: string}
let x = {x = "hello"}
let y(a: myRec) = a.x
y(x);;
y(x);;
--^
error FS0001: This expression was expected to have type
myRec
but here has type
myRec2
So how do I force x to have the type myRec if both myRec and myRec2 has the same signature?
let x = { myRec.x = "hello" }
// or
let x:myRec = { x = "hello" }
// or
let x = { x = "hello" } : myRec
Further details and examples are available in the documentation.
EDIT: Incorporated alternatives from comments.
Yes you can:
let x = { new myRec() with x = "hello" }
use and to assign more fields:
let x = { new myRec3() with x = "hello" and y = "bye" }

Converting byte to an instance of an enum in F#

Let's consider the following enum in C#
public enum ScrollMode : byte
{
None = 0,
Left = 1,
Right = 2,
Up = 3,
Down = 4
}
The F# code receives a byte and has to return an instance of the enum
I have tried
let mode = 1uy
let x = (ScrollMode)mode
(Of course in the real application I do not get to set 'mode',
it is received as part of network data).
The example above does not compile, any suggestions?
For enums whose underlying type is 'int', the 'enum' function will do the conversion, but for non-int enums, you need 'LanguagePrimitives.EnumOfValue', a la:
// define an enumerated type with an sbyte implementation
type EnumType =
| Zero = 0y
| Ten = 10y
// examples to convert to and from
let x = sbyte EnumType.Zero
let y : EnumType = LanguagePrimitives.EnumOfValue 10y
(EnumOfValue is listed here
http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/FSharp.Core/Microsoft.FSharp.Core.LanguagePrimitives.html
(now http://msdn.microsoft.com/en-us/library/ee340276(VS.100).aspx )
whereas enum is listed here
http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/FSharp.Core/Microsoft.FSharp.Core.Operators.html
(now http://msdn.microsoft.com/en-us/library/ee353754(VS.100).aspx )
)
let x : ScrollMode = enum mode

Resources