How to implement `Show` interface for parameterized tuple? - interface

I have Coord function that transforms an n-dimensional size to the type of coordinates bounded by given size: Coord [2,3] = (Fin 2, Fin 3).
import Data.Fin
import Data.List
Size : Type
Size = List Nat
Coord : Size -> Type
Coord [] = ()
Coord s#(_ :: _) = foldr1 (,) $ map Fin s
How can I implement Show interface for Coord s?
If I understand it correctly, the problem is that with s erased at compile time there is no way to know what the actual type of Coord s is. So my best attempt is this abomination:
show' : {s : Size} -> Coord s -> String
show' {s=[]} = show
show' {s=[_]} = show
show' {s=[_,_]} = show
show' = ?show'_rhs
{s : Size} -> Show (Coord s) where
show = show'
foo : {s : Size} -> Coord s -> String
foo x = show' x -- compiles and works
foo x = show x -- error
Error: While processing right hand side of foo. Can't find an implementation for Show (Coord s).
22 | foo : {s : Size} -> Coord s -> String
23 | foo x = show' x
24 | foo x = show x
^^^^^^

(,) already has a Show implemention. Coords is just an alias not a datatype, it can't have separate interface implementations.

Related

Ways to handle collections of interfaces with generic lambdas

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)
|]

Combine prisms to focus on a value regardless of a branch

I have a sum type of possible outcomes, and in every outcome there is a certain "Result" that I want to focus on. I know how to get that "Result" from each of the outcomes (I have a bunch of prisms for that), but I don't know how to combine these prisms so that I can grab the "Result" from the whole sumtype, without worrying which case I'm on.
Simplified example:
type OneAnother = Either Int Int
exampleOneAnother :: OneAnother
exampleOneAnother = Left 10
_one :: Prism' OneAnother Int
_one = _Left
_another :: Prism' OneAnother Int
_another = _Right
_result :: Lens' OneAnother Int
_result = ???
-- How can I combine _one and _another to get result regardless whether its left or right ?
Once a prism comes to focus, it loses the context. So I don't see a way to define _result in terms of _one and _another. But you can certainly do better than resorting to unsafePartial:
import Data.Lens.Lens (Lens', lens)
import Data.Profunctor.Choice ((|||), (+++))
type OneAnother = Either Int Int
_result :: Lens' OneAnother Int
_result = lens getter setter
where
getter = identity ||| identity
setter e x = (const x +++ const x) e
Stole this from the profunctor-lens repository:
-- | Converts a lens into the form that `lens'` accepts.
lensStore :: forall s t a b . ALens s t a b -> s -> Tuple a (b -> t)
lensStore l = withLens l (lift2 Tuple)
It isn't exported somehow. With that help, the following solution should be generic enough:
import Prelude
import Control.Apply (lift2)
import Data.Lens.Common
import Data.Lens.Lens
import Data.Lens.Prism
import Data.Profunctor.Choice ((|||), (+++))
import Data.Tuple
_result :: Lens' OneAnother Int
_result = lens getter setter
where
getter = identity ||| identity
setter e x = (const x +++ const x) e
lensStore :: forall s t a b . ALens s t a b -> s -> Tuple a (b -> t)
lensStore l = withLens l (lift2 Tuple)
data ABC
= A Int
| B (Tuple Boolean Int)
| C OneAnother
lensABCInt :: Lens' ABC Int
lensABCInt = lens' case _ of
A i -> map A <$> lensStore identity i
B i -> map B <$> lensStore _2 i
C i -> map C <$> lensStore _result i
Here ABC is your target sum type. As long as its each variant has a lens, you have a lens for it as a whole.
This is the best I've got so far. Yes, unsafePartial, explicit case matching ... Really hope there is something better.
_result :: Lens' OneAnother Int
_result = lens getter setter
where
getter :: OneAnother -> Int
getter x#(Left _) = unsafePartial $ fromJust $ preview _one x
getter x#(Right _) = unsafePartial $ fromJust $ preview _another x
setter :: OneAnother -> Int -> OneAnother
setter (Left _) x = review _one x
setter (Right _) x = review _another x

Purescript: Could not match type

In the REPL this works:
> mm n = (\n -> n * 2) <$> n
> mm (2:3:Nil)
(4 : 6 : Nil)
in a file this compiles and I can run it:
squareOf ls =
map (\n -> n * n) ls
however when I add a type definition to that function
squareOf :: List Int -> Int
squareOf ls =
map (\n -> n * n) ls
I get an error:
Could not match type
List Int
with type
Int
while checking that type t0 t1
is at least as general as type Int
while checking that expression (map (\n ->
(...) n
)
)
ls
has type Int
in value declaration squareOf
where t0 is an unknown type
t1 is an unknown type
I tried changing the signature to a type alias of the list, and also I tried a forall definition with no luck.
If I inspect the definition created when I don't put signatures in my function I get:
forall t2 t3. Functor t2 => Semiring t3 => t2 t3 -> t2 t3
Can anyone explain why my signature is incorrect and also why am I getting this signature for the function?
Cheers
Edit: Thanks for the comments, updating the fn definition so it returns a List Int as well, and , of course it solves the problem
Assuming you're repl function is the behaviour you're after, you've missed out the map operator (<$>) in your later definitions.
Your repl function (with variables renamed for clarity) has the type:
mm :: forall f. Functor f => f Int -> f Int
mm ns = (\n -> n * 2) <$> ns
Which is to say: mm maps "times two" to something that is mappable" (i.e. a Functor)
Aside: you could be more concise/clear in your definition here:
mm :: forall f. Functor f => f Int -> f Int
mm = map (_*2)
This is similar to your squareOf definition, only now you're squaring so your use of (*) is more general:
squareOf :: forall f. Functor f => Semiring n => f n -> f n
squareOf = map \n -> n * n
Because (*) is a member of the Semiring typeclass.
But the signature you gave it suggests you're after some kind of fold? Let me know what output you expect from your squareOf function and I'll update the answer accordingly.
Here is map:
class Functor f where
map :: forall a b. (a -> b) -> f a -> f b
Narrowing to List Int and Int -> Int, the compiler infers
map :: (Int -> Int) -> List Int -> List Int
So, in squareOf, the expression reduces to a list of integers, not an integer. That is why the compiler complains.

Optional argument in a method with ocaml

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.

Implementing sequences of sequences in F#

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)