Type error in Elm - functional-programming

I'm new to elm, but not new to functional programming so this error is both frustrating and embarrassing. I wrote a 50 line elm program but I get these elusive type errors. In short, could someone find the type error in this code!!!!
You can paste this code right into the online elm editor.
import Mouse
import Window
--Model
type Tracker = {x:Int, y:Int, th:Float}
tracker:Tracker
tracker = {x=100, y=100, th=0.0}
trkS:Signal Tracker
trkS = constant tracker
dir: Tracker -> (Int, Int) -> (Int,Int) -> Float
dir t (x',y') (w',h') =
let (x,y) = toFloatT (x',y')
(w,h) = toFloatT (w',h')
(dx, dy) = (x - w/2, h/2 - y)
in (atan2 (dy - (toFloat t.y)) (dx - (toFloat t.x)))
dirS:Signal Float
dirS = lift3 dir trkS Mouse.position Window.dimensions
changeV: Float -> Tracker -> Tracker
changeV theta t =
{t | th <- theta }
moveTracker: Int -> Tracker -> Tracker
moveTracker time' t =
let time = toFloat time'
x' = (toFloat t.x) + 3 * time *(cos t.th)
y' = (toFloat t.y) + 3 * time *(sin t.th)
in {t | x <- round x'
, y <- round y'}
step:(Int, Float) -> Tracker -> Tracker
step (dt, dir) = moveTracker dt . changeV dir
render (w',h') trk =
let (w,h) = (toFloat w', toFloat h')
in collage w' h'
[ngon 3 20 |> filled green
|> move (trk.x, trk.y)
, asText (trk.th) |> toForm]
input:Signal (Int,Float)
input =
let delta = lift (round . (\t -> t/20)) (fps 25)
in sampleOn delta (lift2 (,) delta dirS)
main =
lift2 render Window.dimensions (foldp step tracker input)
--Helper functions
toFloatT (x,y) = (toFloat x, toFloat y)
roundF = toFloat . round

The order of actual and expected
I put your code in the online editor and it gave me a lot of expected/actual is Int/Float errors. I think that's something that can be improved, but that's for the mailing list.
What you should know is that the expected/actual types that the compiler tells you about can sometimes be reversed, at least to some peoples intuitions.
Debugging the problem
To debug this problem I first read and tried to understand your code. The code is simple enough, but the goal of the program wasn't immediately clear to me. Anyway that way I didn't spot anything out of the ordinary. I focussed specifically on the code line in main where the compiler said the type error was, but that didn't seem the source of the problem.
Adding type annotations
So I went ahead and added type annotations to the functions that didn't have any yet. Usually the compiler can give you a better pinpointed position when you add more type annotations.
I added:
render: (Int,Int) -> Tracker -> Element
main : Signal Element
toFloatT: (Int,Int) -> (Float,Float)
roundF: Float -> Float
The problem
The compiler was then able to tell me that the error was in the render function. There I noticed that you made floating point values of the window dimensions and didn't use them, and after that used the integers x and y of the Tracker in a tuple in move. And there lies the error, because move takes a tuple of floating points.
The solution
So when you use the following adapted render function, things compile:
render: (Int,Int) -> Tracker -> Element
render (w',h') trk =
let trkPos = toFloatT (trk.x, trk.y)
in collage w' h'
[ngon 3 20 |> filled green
|> move trkPos
, asText (trk.th) |> toForm]
I hope by showing you my way of debugging this type error, you can more easily find a solution next time.
TL;DR
The problem is the render function: you give the move function a tuple of Ints in stead of the tuple of Floats it expects. The fixed and compiling code can be found here.

Related

Handle recursive function within an other function ocaml

If I have one or more recursive functions inside an Ocaml function how can I call them without exit from the main function taking their value as return of the main function?
I'm new in Ocaml so I'll try to explain me better...
If I have :
let function =
let rec recursive1 = ...
...
let rec recursive2 = ...
...
How can I call them inside function to tell it "Hey, do you see this recursive function? Now call it and takes its value."
Because my problem is that Ocaml as return of my functions sees Unit instead of the right return.
I will post the code below :
let change k v list_ =
let rec support k v list_ =
match list_ with
| [] -> []
| (i,value) :: tl -> if i = k
then (k,v) :: tl
else (i,value) :: support k v tl in
let inserted = support k v list_ in inserted
let () =
let k = [ (1,"ciao");(2,"Hola");(3,"Salut") ] in
change 2 "Aufwidersen" k
Change takes as input a key, a value and a (int * string )list and should return the same list of the input but changing the value linked to the key selected ( if in list ).
support, instead, makes the dirty job. It builds a new list and when k is found i = k it changes value and attach the tile, closing the function.
The return of change is unit when it should be (int * string) list. I think because inserted isn't taken as return of the function.
change does not return unit. The error in fact tells you exactly the opposite, that it returns (int * string) list but that it expects unit. And it expects unit because you're assigning it to a () pattern.
I don't know what you actually intend to do with the return value, as right now you don't seem to care about it, but you can fix the error by just assigning it to a name:
let result: (int * string) list =
let k = [ (1,"ciao");(2,"Hola");(3,"Salut") ] in
change 2 "Aufwidersen" k
Since it's not used I've added a type annotation to make sure we're getting what we expect here, as otherwise result could be anything and the compiler wouldn't complain. You don't typically need this if you're going to use result however, as you'd then get an error if the type doesn't unify with its usage.

Elm decrement counter while iterating array

I've recently decided to take a more in depth look at functional programming and I decided to start out with Elm.
I'm very inexperienced at this so I feel like I am actually fighting the concept and the language and that my thought process is all wrong so I was hoping someone could help me with my simple exercises.
I'm trying to create a Minesweeper game, and for starters, I was just trying to populate a grid with mines.
Here's my code so far
import Array exposing (Array)
type State = Hidden | Tagged | Revealed
type alias Cell = {isMine: Bool, nearbyMines: Int, state: State}
type alias Board = Array (Array Cell)
mines : Int
mines = 100
initCell : Cell
initCell =
{isMine = False, nearbyMines = 0, state = Hidden}
generate : Int -> Int -> Board
generate lines cols =
Array.initialize lines (\y ->
Array.initialize cols (\x -> initCell))
markAsMine : Int -> Int -> Cell -> Cell
markAsMine x y cell =
if mines > 0
then {cell | isMine = True}
else cell
fillMines : Int -> Board -> Board
fillMines amount board =
board
|> Array.indexedMap (\y row -> row |> Array.indexedMap (\x cell-> markAsMine x y cell))
Of course, all this will do is mark every cell as a mine, so how do decrement the counter every time I mark a cell as mine?
This should be something trivial, hence why I think I'm struggling with the different programming paradigm!
Thanks in advance for any help,
Cheers!
A more functional approach would try to avoid using state when possible. Instead of thinking about it in terms of traversing a set of cells and decrementing a stateful field telling you how many mines are yet to be placed, it would be more idiomatic to pass in a Set of (x, y) values that have already been determined to be mines.
import Set exposing (Set)
fillMines : Int -> Set ( Int, Int ) -> Board -> Board
fillMines amount mines board =
board
|> Array.indexedMap
(\y row ->
row |> Array.indexedMap (\x cell -> { cell | isMine = Set.member ( x, y ) mines })
)
You then shift the responsibility of determining which (x, y) cells are mines to elsewhere in the application, and since Minesweeper is a randomized game, you'll probably want to create a random set of cells assigned as mines. The type signature could look something like this:
import Random
minefieldGenerator : Int -> Int -> Int -> Random.Generator (Set (Int, Int))
minefieldGenerator lines cols numMines = ...
The implementation of minefieldGenerator is outside the scope of this question, but you can use this generator using Random.generate (which will let the Elm Architecture generate a random number when returned from inside an update function), or you can pass in a known seed value to execute step.

Simple non-optimal unionfind in OCaml

I wrote a OCaml program for union find algorithm. This algorithm I wrote is not optimal and is the simplest version.
I put my OCaml code here because I am not sure whether this code is good enough or not (despite of the algorithm itself), although this code can run without errors.
This is the first time I wrote a complete working thing after I started to learn OCaml, so please help me by reviewing it.
Useful suggestions will help me improving my OCaml skills. Thanks
type union_find = {id_ary : int array; sz_ary : int array};;
let create_union n = {id_ary = Array.init n (fun i -> i);
sz_ary = Array.init n (fun i -> 1)};;
let union u p q =
let rec unionfy id_ary i =
let vp = id_ary.(p) in
let vq = id_ary.(q) in
if i < Array.length id_ary then begin
if i != q && id_ary.(i) = vp then id_ary.(i) <- vq;
unionfy id_ary (i + 1)
end
else print_string "end of union\n"
in
unionfy u.id_ary 0;;
let is_connected u p q = u.id_ary.(p) = u.id_ary.(q);;
First of all,
Am I creating the data structure of union (as in union find) correctly?
Should I include two arrays inside or is there any better way?
Second,
I am using array in this code, but array is mutable which is not that good for fp right?
Is there a way to avoid using array?
Finally,
Overall, is this piece of code good enough?
Anything can be improved?
P.S. I am not using OCaml's object oriented bit yet, as I haven't learnt to that part.
Some comments on the code:
You don't seem to use sz_ary for anything.
Your code iterates through the whole array for each union operation. This is not correct for the standard (Tarjan) union-find. For a linear number of union operations your code produces a quadratic solution. Wikipedia has the standard algorithm: Disjoint-set Data Structure.
To answer your second question: as far as I know, union-find is one of the algorithms for which there's no known functional (immutable) solution with the same complexity as the best imperative solution. Since an array is simply a map from integers to values, you could always translate any array-based solution into an immutable one using maps. As far as I've been able to determine, this would match the best known solution in asymptotic complexity; i.e., it would add an extra factor of log n. Of course there would also be a constant factor that might be large enough to be a problem.
I've implemented union-find a few times in OCaml, and I've always chosen to do it using mutable data. However, I haven't used arrays. I have a record type for my basic objects, and I use a mutable field in each record to point to its parent object. To do path compression, you modify the parent pointer to point to the current root of the tree.
A few stylistic points:
Not sure why unionfy takes id_ary as a parameter since it keeps it constant throughout
don't use Array.init with a constant function. Just use Array.make.
print_string "...\n" is equivalent to print_endline "..."
The following definition can be cleaned up with punning to
let union u p q = to: let union {id_ary; _} p q so that there are no extraneous references to u.
Same punning trick for let is_connected u p q = u.id_ary.(p) = u.id_ary.(q);;
This might be a personal choice but I would get rid of:
let vp = id_ary.(p) in
let vq = id_ary.(q) in
Or at least shove them above the recursive definition so that it's clear they are constant.
EDIT: corrected version
let union {id_ary;_} p q =
let (vp, vq) = (id_ary.(p), id_ary.(q)) in
let rec unionfy i =
if i < Array.length id_ary then begin
if i != q && id_ary.(i) = vp then id_ary.(i) <- vq;
unionfy (i + 1)
end else print_endline "end of union"
in unionfy 0;;

Erlang syntax for nested function with if

I've been looking around and can't find examples of this and all of my syntax wrestling skills are failing me. Can someone please tell me how to make this compile?? My ,s ;s or .s are just wrong I guess for defining a nested function...
I'm aware there is a function for doing string replaces already so I don't need to implement this, but I'm playing with Erlang trying to pick it up so I'm hand spinning some of the basics I need to use..
replace(Whole,Old,New) ->
OldLen = length(Old),
ReplaceInit = fun(Next, NewWhole) ->
if
lists:prefix(Old, [Next|NewWhole]) -> {_,Rest} = lists:split(OldLen-1, NewWhole), New ++ Rest;
true -> [Next|NewWhole]
end,
lists:foldr(ReplaceInit, [], Whole).
Basically I'm trying to write this haskell (also probably bad but beyond the point):
repl xs ys zs =
foldr replaceInit [] xs
where
ylen = length ys
replaceInit y newxs
| take ylen (y:newxs) == ys = zs ++ drop (ylen-1) newxs
| otherwise = y:newxs
The main problem is that in an if you are only allowed to use guards as tests. Guards are very restricted and, amongst other things, calls to general Erlang functions are not allowed. Irrespective of whether they are part of the OTP release or written by you. The best solution for your function is to use case instead of if. For example:
replace(Whole,Old,New) ->
OldLen = length(Old),
ReplaceInit = fun (Next, NewWhole) ->
case lists:prefix(Old, [Next|NewWhole]) of
true ->
{_,Rest} = lists:split(OldLen-1, NewWhole),
New ++ Rest;
false -> [Next|NewWhole]
end
end,
lists:foldr(ReplaceInit, [], Whole).
Because of this if is not used that often in Erlang. See about if and about guards in the Erlang documentation.

Extending OCaml Maps to formattable Maps

I have made a functor for format-able sets, as follows:
module type POrderedType =
sig
type t
val compare : t -> t -> int
val format : Format.formatter -> t -> unit
end
module type SET =
sig
include Set.S
val format : Format.formatter -> t -> unit
end
module MakeSet (P : POrderedType) : SET with type elt = P.t
Implementation of this is straightforward:
module MakeSet (P : OrderedType) =
struct
include Set.Make(P)
let format ff s =
let rec format' ff = function
| [] -> ()
| [v] -> Format.fprintf ff "%a" format v
| v::tl -> Format.fprintf ff "%a,# %a" format v format' tl in
Format.fprintf ff "#[<4>%a#]" format' (elements s)
end
I wanted to do something similar with maps. POrderedType is fine for keys, but I need a simpler type for values:
module type Printable =
sig
type t
val format : Format.formatter -> t -> unit
end
Then I wanted to do something similar to what I had done for sets, but I run into the following problem. Map.S values have type +'a t. I can't figure out a way to include the Map.S definition while constraining the 'a to be a Printable.t. What I want is something like the following (ignoring the fact that it is illegal):
module MakeMap (Pkey : POrderedType) (Pval : Printable) :
MAP with type key = Pkey.t and type 'a t = 'a t constraint 'a = Pval.t
Is there any way to do what I want without copying the entire signature of Map by hand?
I think the cleanest way to propose a printing function for polymorphic maps is to make the map printing function parametric over the values printing function. You can think of it this way:
functor-defined types are defined at the functor level, so providing functions for them is best done by adding new functor parameters (or enriching existing ones)
parametric types are bound (generalized) at the value level, so providing functions for them is best done by adding new parameters to the value
In OCaml, convenience tend to make people favor parametric polymorphism over functorization when possible. Functorization is sometimes necessary to enforce some type safety (here it's used to make sure that maps over different comparison functions have incompatible types), but otherwise people rather try to have polymorphism. So you're actually in the lucky situation here.
If you really want to have a functor producing monomorphic maps, well, I'm afraid you will have to copy the whole map interface and adapt it in the momonorphic case -- it's not much work.

Resources