Reputation: 23
From an Elm newbie but long-time Haskeller, a quick query.
The aim: There is a map with towns on it at designated positions on it, and I want to check if the user click is close to a town, and identify that town.
so, I collect the signal as usual:
clickPositionsSignal = sampleOn Mouse.clicks Mouse.position
that gives me a Tuple, which I want to turn into an Int (denoting the number of the nearest town). Towns are designated as
positions : [Position]
type Position = {number : Int, x : Int, y : Int}
the function to do this is:
whichTown : (Int,Int) -> Int
whichTown (x,y) =
let pz = map (\p -> getDistance p.x p.y x y) positions |> head
in pz.number
Now, I need to apply this function to my clickPositionsSignal.
Looking around various examples, I modified some code to....
whichLocationSignal : Signal Int
whichLocationSignal =
let wbl (x,y) = whichTown(x,y)
in wbl <~ clickPositionsSignal
.... and this works. I get the number of the nearest town.
But this is hopelessly cumbersome and duplicative. The question is why can I not simply write:
whichLocationSignal = whichTown clickPositionsSignal
That line throws up multiple Type Errors which I am not yet experienced enough to interpret
Upvotes: 1
Views: 204
Reputation: 5958
It should be:
whichLocationSignal = whichTown <~ clickPositionsSignal
or
whichLocationSignal = lift whichTown clickPositionsSignal
(which you already figured out yourself)
So a full version of your code that gives these type-errors would be:
import Mouse
type Position = {number : Int, x : Int, y : Int}
clickPositionsSignal : Signal (Int,Int)
clickPositionsSignal = sampleOn Mouse.clicks Mouse.position
positions : [Position]
positions = []
getDistance x1 y1 x2 y2 = { number = 0 }
whichTown : (Int,Int) -> Int
whichTown (x,y) =
let pz = map (\p -> getDistance p.x p.y x y) positions |> head
in pz.number
whichLocationSignal : Signal Int
whichLocationSignal = whichTown clickPositionsSignal
The type errors I then get are:
Type error on line 19, column 33 to 53:
clickPositionsSignal
Expected Type: (Int, Int)
Actual Type: Int
Type error on line 19, column 33 to 53:
clickPositionsSignal
Expected Type: Signal.Signal
Actual Type: (Int)
Type error on line 19, column 23 to 32:
whichTown
Expected Type: Int
Actual Type: Signal.Signal Int
I admit, these type errors are confusing.
(You might even say they are incorrect. All I can say to that is this is the current quality of type errors that you get, sorry!)
One basic tip when a type error from Elm doesn't make sense is to see if it makes more sense when you flip the expected/actual. Then the first type error makes no sense. But the second gives some information: clickPositionsSignal
is somehow expected to have a type Int
, not some Signal
. Together with the third error message this starts to make sense: whichTown
does something the other way around where an Int
should be given but you get a Signal
...
At that point you can find the uses of these two together, and once you note that whichTown
works on (Int,Int)
and clickPositionsSignal : Signal (Int,Int)
, you've found your error and the compiler messages make some kind of crooked sense.
The fix as stated above is to use lift : (a -> b) -> Signal a -> Signal b
to "lift" the function (whichTown
) to the Signal
"level". Most people prefer to use the infix operator <~
.
Upvotes: 1