I am currently trying to experiment with F# and I am struggling a bit with how to best handle a scenario such as described with these types:
[<Interface>]
type IStuff<'a> =
abstract member Update: 'a -> 'a
type Stuff1<'a> = {
Pos : int
Sprite : string
Temperature : float
UpdateBehaviour : 'a -> 'a
} with
interface IStuff<'a> with
member this.Update p =
this.UpdateBehaviour p
static member New f = {
Pos = 0
Sprite = "Sprite"
Temperature = 0.0
UpdateBehaviour = f
}
type Stuff2<'a> = {
Pos : int
UpdateBehaviour : 'a -> 'a
} with
interface IStuff<'a> with
member this.Update p =
this.UpdateBehaviour p
static member New f = {
Pos = 0
UpdateBehaviour = f
}
Now ideally I would like to have both Stuff1 and Stuff2 types together in a collection where each particle would call its specific update function which may change based on the type (as types have varying fields of data) or simply differs between the same types.
I have tried multiple things with approaches such as this.
let stuffArr< 'T when 'T :> IStuff<'T>> = [|
Stuff1.New<_> (fun p -> printfn "s1"; p)
Stuff2.New<_> (fun p -> printfn "s2"; p)
|]
Which obviously does not function as the compiler identifies that these two are clearly different types with Stuff1 being type ´aand Stuff2 being type ´b.
I could also do an approach such as this.
let stuffArr : obj list = [
Stuff1.New<_> (fun p -> printfn "p1"; p)
Stuff2.New<_> (fun p -> printfn "p2"; p)
]
let iterateThrough (l : obj list) =
l
|> List.map (fun p ->
let s = p :?> IStuff<_>
s.Update p)
Which functions obviously but as you all may now, I essentially turn off the type system and I am doing a dynamic down cast which frankly scares me.
So is there a better way to accomplish this? Thanks in advance!
There are ways to get a bit more checking with the structure you have, but none of those are very nice. However, I think that the fundamental issue is that you are trying to use F# as an object-oriented language. If you use a more functional design, this will look much nicer.
I would define Stuff as a discriminated union with the different kinds of stuff:
type Stuff =
| Stuff1 of pos:int * sprite:string * temperature:float
| Stuff2 of pos:int
let stuffArr = [
Stuff1(0, "Sprite", 0.0)
Stuff2(0)
]
The update operation would then be just a function that uses pattern matching to handle the two different kinds of stuff you have:
let update stuff =
match stuff with
| Stuff1 _ -> ...
| Stuff2 _ -> ...
The result is that you can update all stuff and get a new list using just List.map:
List.map update stuffArr
I get the feeling that what you're showing above may not have the same complexity as what you're actually trying to do. If that's the case, Tomas' solution may be too simple for you to use. If you have some reason to prefer using the interface you described above, you could define stuffArr as follows
let stuffArr : IStuff<_>[] = [|
Stuff1.New<int> (fun p -> printfn "s1"; p)
Stuff2.New<int> (fun p -> printfn "s2"; p)
|]
Here I assumed the generic parameter to be int. It could be any other type - I assume you have something in mind. However, the generic parameter for each entry in the array needs to be the same. If you need different generic parameters, you would need to wrap them in a discriminated union like so
type MyWrapper = String of string | Int of int
let stuffArr : IStuff<_>[] = [|
Stuff1.New<MyWrapper> (fun p -> printfn "s1"; p)
Stuff2.New<MyWrapper> (fun p -> printfn "s2"; p)
|]
or using the build-in Choice type
let stuffArr : IStuff<_>[] = [|
Stuff1.New<Choice<string, int>> (fun p -> printfn "s1"; p)
Stuff2.New<Choice<string, int>> (fun p -> printfn "s2"; p)
|]
Related
Is there any way to do something like
first = {x:0}
second = {x:1,y:1}
both = [first, second]
such that both is inferred as {x::Int | r} or something like that?
I've tried a few things:
[{x:3}] :: Array(forall r. {x::Int|r}) -- nope
test = Nil :: List(forall r. {x::Int|r})
{x:1} : test -- nope
type X r = {x::Int | r}
test = Nil :: List(X) -- nope
test = Nil :: List(X())
{x:1} : test
{x:1, y:1} : test -- nope
Everything I can think of seems to tell me that combining records like this into a collection is not supported. Kind of like, a function can be polymorphic but a list cannot. Is that the correct interpretation? It reminds me a bit of the F# "value restriction" problem, though I thought that was just because of CLR restrictions whereas JS should not have that issue. But maybe it's unrelated.
Is there any way to declare the list/array to support this?
What you're looking for is "existential types", and PureScript just doesn't support those at the syntax level the way Haskell does. But you can roll your own :-)
One way to go is "data abstraction" - i.e. encode the data in terms of operations you'll want to perform on it. For example, let's say you'll want to get the value of x out of them at some point. In that case, make an array of these:
type RecordRep = Unit -> Int
toRecordRep :: forall r. { x :: Int | r } -> RecordRep
toRecordRep {x} _ = x
-- Construct the array using `toRecordRep`
test :: Array RecordRep
test = [ toRecordRep {x:1}, toRecordRep {x:1, y:1} ]
-- Later use the operation
allTheXs :: Array Int
allTheXs = test <#> \r -> r unit
If you have multiple such operations, you can always make a record of them:
type RecordRep =
{ getX :: Unit -> Int
, show :: Unit -> String
, toJavaScript :: Unit -> Foreign.Object
}
toRecordRep r =
{ getX: const r.x
, show: const $ show r.x
, toJavaScript: const $ unsafeCoerce r
}
(note the Unit arguments in every function - they're there for the laziness, assuming each operation could be expensive)
But if you really need the type machinery, you can do what I call "poor man's existential type". If you look closely, existential types are nothing more than "deferred" type checks - deferred to the point where you'll need to see the type. And what's a mechanism to defer something in an ML language? That's right - a function! :-)
newtype RecordRep = RecordRep (forall a. (forall r. {x::Int|r} -> a) -> a)
toRecordRep :: forall r. {x::Int|r} -> RecordRep
toRecordRep r = RecordRep \f -> f r
test :: Array RecordRep
test = [toRecordRep {x:1}, toRecordRep {x:1, y:1}]
allTheXs = test <#> \(RecordRep r) -> r _.x
The way this works is that RecordRep wraps a function, which takes another function, which is polymorphic in r - that is, if you're looking at a RecordRep, you must be prepared to give it a function that can work with any r. toRecordRep wraps the record in such a way that its precise type is not visible on the outside, but it will be used to instantiate the generic function, which you will eventually provide. In my example such function is _.x.
Note, however, that herein lies the problem: the row r is literally not known when you get to work with an element of the array, so you can't do anything with it. Like, at all. All you can do is get the x field, because its existence is hardcoded in the signatures, but besides the x - you just don't know. And that's by design: if you want to put anything into the array, you must be prepared to get anything out of it.
Now, if you do want to do something with the values after all, you'll have to explain that by constraining r, for example:
newtype RecordRep = RecordRep (forall a. (forall r. Show {x::Int|r} => {x::Int|r} -> a) -> a)
toRecordRep :: forall r. Show {x::Int|r} => {x::Int|r} -> RecordRep
toRecordRep r = RecordRep \f -> f r
test :: Array RecordRep
test = [toRecordRep {x:1}, toRecordRep {x:1, y:1}]
showAll = test <#> \(RecordRep r) -> r show
Passing the show function like this works, because we have constrained the row r in such a way that Show {x::Int|r} must exist, and therefore, applying show to {x::Int|r} must work. Repeat for your own type classes as needed.
And here's the interesting part: since type classes are implemented as dictionaries of functions, the two options described above are actually equivalent - in both cases you end up passing around a dictionary of functions, only in the first case it's explicit, but in the second case the compiler does it for you.
Incidentally, this is how Haskell language support for this works as well.
Folloing #FyodorSoikin answer based on "existential types" and what we can find in purescript-exists we can provide yet another solution.
Finally we will be able to build an Array of records which will be "isomorphic" to:
exists tail. Array { x :: Int | tail }
Let's start with type constructor which can be used to existentially quantify over a row type (type of kind #Type). We are not able to use Exists from purescript-exists here because PureScript has no kind polymorphism and original Exists is parameterized over Type.
newtype Exists f = Exists (forall a. f (a :: #Type))
We can follow and reimplement (<Ctrl-c><Ctrl-v> ;-)) definitions from Data.Exists and build a set of tools to work with such Exists values:
module Main where
import Prelude
import Unsafe.Coerce (unsafeCoerce)
import Data.Newtype (class Newtype, unwrap)
newtype Exists f = Exists (forall a. f (a :: #Type))
mkExists :: forall f a. f a -> Exists f
mkExists r = Exists (unsafeCoerce r :: forall a. f a)
runExists :: forall b f. (forall a. f a -> b) -> Exists f -> b
runExists g (Exists f) = g f
Using them we get the ability to build an Array of Records with "any" tail but we have to wrap any such a record type in a newtype before:
newtype R t = R { x :: Int | t }
derive instance newtypeRec :: Newtype (R t) _
Now we can build an Array using mkExists:
arr :: Array (Exists R)
arr = [ mkExists (R { x: 8, y : "test"}), mkExists (R { x: 9, z: 10}) ]
and process values using runExists:
x :: Array [ Int ]
x = map (runExists (unwrap >>> _.x)) arr
For example, I would like a tactic that would iterate over all the resolve hints in a given HintDb and for each resolve hint h, it would do a pose h. . Is this possible? If so, how?
In Coq, there is not (unless you do fancy things with shelve and backtracking), but it is pretty straightforward in OCaml. For example, in the Fiat project, we have such tactics. For Coq 8.7:
In hint_db_extra_tactics.ml:
module WITH_DB =
struct
open Tacticals.New
open Names
open Ltac_plugin
(* [tac] : string representing identifier *)
(* [args] : tactic arguments *)
(* [ltac_lcall] : Build a tactic expression calling a variable let-bound to a tactic == [F] args *)
let ltac_lcall tac args =
Tacexpr.TacArg(Loc.tag ## Tacexpr.TacCall(Loc.tag ## (Misctypes.ArgVar(Loc.tag ## Names.Id.of_string tac),args)))
(* [ltac_letin] : Build a let tactic expression. let x := e1 in e2 *)
let ltac_letin (x, e1) e2 =
Tacexpr.TacLetIn(false,[(Loc.tag ## Names.Id.of_string x),e1],e2)
(* [ltac_apply] : Run a tactic with arguments... *)
let ltac_apply (f: Tacinterp.Value.t) (arg:Tacinterp.Value.t) =
let open Geninterp in
let ist = Tacinterp.default_ist () in
let id = Id.of_string "X" in
let idf = Id.of_string "F" in
let ist = { ist with Tacinterp.lfun = Id.Map.add idf f (Id.Map.add id arg ist.lfun) } in
let arg = Tacexpr.Reference (Misctypes.ArgVar (Loc.tag id)) in
Tacinterp.eval_tactic_ist ist
(ltac_lcall "F" [arg])
(* Lift a constructor to an ltac value. *)
let to_ltac_val c = Tacinterp.Value.of_constr c
let with_hint_db dbs tacK =
let open Proofview.Notations in
(* [dbs] : list of hint databases *)
(* [tacK] : tactic to run on a hint *)
Proofview.Goal.nf_enter begin
fun gl ->
let syms = ref [] in
let _ =
List.iter (fun l ->
(* Fetch the searchtable from the database*)
let db = Hints.searchtable_map l in
(* iterate over the hint database, pulling the hint *)
(* list out for each. *)
Hints.Hint_db.iter (fun _ _ hintlist ->
syms := hintlist::!syms) db) dbs in
(* Now iterate over the list of list of hints, *)
List.fold_left
(fun tac hints ->
List.fold_left
(fun tac (hint : Hints.full_hint) ->
let hint1 = hint.Hints.code in
Hints.run_hint hint1
(fun hint2 ->
(* match the type of the hint to pull out the lemma *)
match hint2 with
Hints.Give_exact ((lem, _, _) , _)
| Hints.Res_pf ((lem, _, _) , _)
| Hints.ERes_pf ((lem, _, _) , _) ->
let this_tac = ltac_apply tacK (Tacinterp.Value.of_constr lem) in
tclORELSE this_tac tac
| _ -> tac))
tac hints)
(tclFAIL 0 (Pp.str "No applicable tactic!")) !syms
end
let add_resolve_to_db lem db =
let open Proofview.Notations in
Proofview.Goal.nf_enter begin
fun gl ->
let _ = Hints.add_hints true db (Hints.HintsResolveEntry [({ Vernacexpr.hint_priority = Some 1 ; Vernacexpr.hint_pattern = None },false,true,Hints.PathAny,lem)]) in
tclIDTAC
end
end
In hint_db_extra_plugin.ml4:
open Hint_db_extra_tactics
open Stdarg
open Ltac_plugin
open Tacarg
DECLARE PLUGIN "hint_db_extra_plugin"
TACTIC EXTEND foreach_db
| [ "foreach" "[" ne_preident_list(l) "]" "run" tactic(k) ] ->
[ WITH_DB.with_hint_db l k ]
END
TACTIC EXTEND addto_db
| [ "add" constr(name) "to" ne_preident_list(l) ] ->
[ WITH_DB.add_resolve_to_db (Hints.IsConstr (name, Univ.ContextSet.empty)) l]
END;;
In hint_db_extra_plugin.mllib:
Hint_db_extra_tactics
Hint_db_extra_plugin
In HintDbExtra.v:
Declare ML Module "hint_db_extra_plugin".
Using this to solve the example posed in the problem statement, we can add:
In _CoqProject:
-R . Example
-I .
HintDbExtra.v
PoseDb.v
hint_db_extra_plugin.ml4
hint_db_extra_plugin.mllib
hint_db_extra_tactics.ml
In PoseDb.v:
Require Import HintDbExtra.
Ltac unique_pose v :=
lazymatch goal with
| [ H := v |- _ ] => fail
| _ => pose v
end.
Goal True.
repeat foreach [ core ] run unique_pose.
If you want to run a tactic on each hint in the hint database (rather than running a tactic on each hint in succession, until you find one that succeeds), you can change the tclORELSE in with_hint_db to some sort of sequencing operator (e.g., tclTHEN).
I'm working on making my data types general instead of taking in the OpenGL type GLfloat. So I started making it take in type a and then just replacing everything with that.
Now, I've come to a point where I'm setting uniform variables, but they take in GLfloat's. I'm using a library called GLUtil which makes it a bit easier, which has provided a class AsUniform, to check whether the type can be a uniform variable or not. I stick it in my type signature, but it stills gives me an error. Here's the code:
-- | Sets the modelview and projection matrix uniform variables.
mvpUnif :: (GL.UniformComponent a, Num a, Epsilon a, Floating a, AsUniform a) => (GLState a) -> ShaderProgram -> IO ()
mvpUnif state p = do
-- Check if view and projection matrices are there, else set them to the identity.
let vMat = case vMatrix state of
Just v -> v
Nothing -> getIdentity
let pMat = case pMatrix state of
Just p -> p
Nothing -> getIdentity
-- Multiply model and view matrix together.
let mvMatrix = vMat !*! mMatrix state
setUniform p uModelViewMatrixVar mvMatrix
setUniform p uProjectionMatrixVar pMat
and the error:
Could not deduce (AsUniform (V4 (V4 a)))
arising from a use of `setUniform'
from the context (GL.UniformComponent a,
Num a,
Epsilon a,
Floating a,
AsUniform a)
bound by the type signature for
mvpUnif :: (GL.UniformComponent a, Num a, Epsilon a, Floating a
,
AsUniform a) =>
GLState a -> ShaderProgram -> IO ()
at src\Graphics\FreeD\Shaders\DefaultShaders.hs:194:12-119
In a stmt of a 'do' block:
setUniform p uModelViewMatrixVar mvMatrix
In the expression:
do { let vMat = ...;
let pMat = ...;
let mvMatrix = vMat !*! mMatrix state;
setUniform p uModelViewMatrixVar mvMatrix;
.... }
In an equation for `mvpUnif':
mvpUnif state p
= do { let vMat = ...;
let pMat = ...;
let mvMatrix = ...;
.... }
V4 is made an instance of AsUniform, as well as M44, which is a type for (V4 (V4 a)), which I thought might be the issue, so I'm not sure why it's acting up.
Here's the source for the class:
http://hackage.haskell.org/package/GLUtil-0.8.5/docs/Graphics-GLUtil-Linear.html
Thanks!
Try adding -XFlexibleContexts and the constraint, literally, to your existing answer:
{-# LANGUAGE FlexibleContexts #-}
mvpUnif :: ( GL.UniformComponent a
, Num a
, Epsilon a
, Floating a
, AsUniform a
, AsUniform (V4 (V4 a))
) => (GLState a) -> ShaderProgram -> IO ()
Usually this is the routine for constraints that aren't inferrable, or where constraints need to be transitively included in all call sites. This happens to me all the time with MonadState et al. In this case, setUniform is the culprit.
I encounter a problem with a optional argument in a method class.
let me explain. I have a pathfinding class graph (in the Wally module) and one his method shorthestPath. It use a optional argument. The fact is when I call (with or not the optional argument) this method OCaml return a conflict of type :
Error: This expression has type Wally.graph
but an expression was expected of type
< getCoor : string -> int * int;
getNearestNode : int * int -> string;
shorthestPath : src:string -> string -> string list; .. >
Types for method shorthestPath are incompatible
whereas shorthestPath type is :
method shorthestPath : ?src:string -> string -> string list
I same tried to use the option format for a optional argument :
method shorthestPath ?src dst =
let source = match src with
| None -> currentNode
| Some node -> node
in
...
Only in the case where I remove the optionnal argument, OCaml stop to insult me.
Thank you in advance for your help :)
It is not very clear what your situation is but I guess the following:
let f o = o#m 1 + 2
let o = object method m ?l x = match l with Some y -> x + y | None -> x
let () = print_int (f o) (* type error. Types for method x are incompatible. *)
The use site (here the definition of f), the type of object is inferred from its context. Here, o : < x : int -> int; .. >. The method x's type is fixed here.
The object o defined later is independent from the argument of f and has the type < m : ?l:int -> int -> int; .. >. And unfortunately this type is incompatible with the other.
A workaround is to give more typing context to the use site about the optional argument:
let f o = o#m ?l:None 1 + 2 (* Explicitly telling there is l *)
let o = object method m ?l x = match l with Some y -> x + y | None -> x end
Or give the type of o:
class c = object
method m ?l x = ...
...
end
let f (o : #c) = o#m 1 + 2 (* Not (o : c) but (o : #c) to get the function more polymoprhic *)
let o = new c
let () = print_int (f o)
I think this is easier since there is usually a class declaration beforehand.
This kind of glitch between higher order use of functions with optional arguments happens also outside of objects. OCaml tries to resolve it nicely but it is not always possible. In this case:
let f g = g 1 + 2
let g ?l x = match l with Some y -> x + y | None -> x
let () = print_int (f g)
is nicely typed. Nice!
The key rule: if OCaml cannot infer about omitted optional arguments, try giving some type context about them explicitly.
I am trying to expose a 2 dimensional array as a sequence of sequences on an object(to be able to do Seq.fold (fun x -> Seq.fold (fun ->..) [] x) [] mytype stuff specifically)
Below is a toy program that exposes the identical functionality.
From what I understand there is a lot going on here, first of IEnumerable has an ambiguous overload and requires a type annotation to explicitly isolate which IEnumerable you are talking about.
But then there can be issues with unit as well requiring additional help:
type blah =
class
interface int seq seq with
member self.GetEnumerator () : System.Collections.Generic.IEnumerable<System.Collections.Generic.IEnumerable<(int*int)>> =
seq{ for i = 0 to 10 do
yield seq { for j=0 to 10 do
yield (i,j)} }
end
Is there some way of getting the above code to work as intended(return a seq<seq<int>>) or am I missing something fundamental?
Well for one thing, GetEnumerator() is supposed to return IEnumerator<T> not IEnumerable<T>...
This will get your sample code to compile.
type blah =
interface seq<seq<(int * int)>> with
member self.GetEnumerator () =
(seq { for i = 0 to 10 do
yield seq { for j=0 to 10 do
yield (i,j)} }).GetEnumerator()
interface System.Collections.IEnumerable with
member self.GetEnumerator () =
(self :> seq<seq<(int * int)>>).GetEnumerator() :> System.Collections.IEnumerator
How about:
let toSeqOfSeq (array:array<array<_>>) = array |> Seq.map (fun x -> x :> seq<_>)
But this works with an array of arrays, not a two-dimensional array. Which do you want?
What are you really out to do? A seq of seqs is rarely useful. All collections are seqs, so you can just use an array of arrays, a la
let myArrayOfArrays = [|
for i = 0 to 9 do
yield [|
for j = 0 to 9 do
yield (i,j)
|]
|]
let sumAllProds = myArrayOfArrays |> Seq.fold (fun st a ->
st + (a |> Seq.fold (fun st (x,y) -> st + x*y) 0) ) 0
printfn "%d" sumAllProds
if that helps...
module Array2D =
// Converts 2D array 'T[,] into seq<seq<'T>>
let toSeq (arr : 'T [,]) =
let f1,f2 = Array2D.base1 arr , Array2D.base2 arr
let t1,t2 = Array2D.length1 arr - f1 - 1 , Array2D.length2 arr - f2 - 1
seq {
for i in f1 .. t1 do
yield seq {
for j in f2 .. t2 do
yield Array2D.get arr i j }}
let myArray2D : string[,] = array2D [["a1"; "b1"; "c1"]; ["a2"; "b2"; "c2"]]
printf "%A" (Array2D.toSeq myArray2D)