Question

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
Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top