Reputation: 473
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
Upvotes: 2
Views: 666
Reputation: 5958
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.
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.
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 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.
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.
The problem is the render
function: you give the move
function a tuple of Int
s in stead of the tuple of Float
s it expects. The fixed and compiling code can be found here.
Upvotes: 5