The following code is supposed to produce a button, which when pressed creates a box (and a button to remove the box on it)
import Graphics.Input
import Signal (..)
import Signal
import Mouse
import Text (Text, asText, plainText)
import Graphics.Element (..)
import Graphics.Collage (..)
import Color (..)
import List
import Dict
-- x y id | id
type Event = Add (Float, Float, Int) | Remove (Int) | Maybe
makebox : Int -> Element
makebox id =
let (w, h) = (30, 30)
in flow down
[ layers [plainText "aaaa", collage w h [square 30 |> filled red]]
, button_remove id ]
add = Signal.channel (0,0,0)
remove = Signal.channel (0)
button_add x y = Graphics.Input.button (Signal.send add (x, y, 2)) "add a box"
button_remove id = Graphics.Input.button (Signal.send remove (id)) "remove me"
main =
let update event =
case event of
Add (x, y, id) -> Dict.insert id ((x,y), ((makebox id)))
Remove (id) -> Dict.remove id
Maybe -> identity
in Signal.map (\dict -> flow down
[ button_add 10.0 20.0 --makes add & remove buttons
, collage 500 500 (List.map (\(Just ((x,y), makebox)) -> move (x,y) makebox)
(Dict.values dict)) --draws the dict
]) --map function argument
(foldp update Dict.empty
(merge
(Add <~ (Signal.subscribe add)) --pipes button channels into events
(Remove <~ (Signal.subscribe remove)))) --map signal argument
However, it produces this type error:
Type mismatch between the following types on line 40, column 14 to 20:
((Int, Int))
Maybe.Maybe
It is related to the following expression:
update
I don't see where this error is coming from, where is the Maybe.Maybe being passed into update
, and how do I fix it?
Find & replace the line with the collage
call in main
to this:
, collage 500 500 (List.map (\((x,y), makebox) -> move (x,y) (toForm makebox))
That's a lot of code. I had to change the style a little to understand, how it works. What I did was move a lot more functions to the top-level and give them type annotations. I also changed the button_add
/remove
to camelCase, because that's the standard Elm naming convention. This is the result:
import Graphics.Input
import Signal (..)
import Signal
import Mouse
import Text (Text, asText, plainText)
import Graphics.Element (..)
import Graphics.Collage (..)
import Color (..)
import List
import Dict
-- x y id | id
type Event = Add (Float, Float, Int) | Remove (Int) | Maybe
type alias Model = Dict.Dict Int ((Float,Float), Element)
makebox : Int -> Element
makebox id =
let (w, h) = (30, 30)
in flow down
[ layers [plainText "aaaa", collage w h [square 30 |> filled red]]
, buttonRemove id ]
add : Signal.Channel (Float,Float,Int)
add = Signal.channel (0,0,0)
remove : Signal.Channel Int
remove = Signal.channel 0
buttonAdd : Float -> Float -> Element
buttonAdd x y = Graphics.Input.button (Signal.send add (x, y, 2)) "add a box"
buttonRemove : Int -> Element
buttonRemove id = Graphics.Input.button (Signal.send remove id) "remove me"
update : Event -> Model -> Model
update event =
case event of
Add (x, y, id) -> Dict.insert id ((x,y), makebox id)
Remove (id) -> Dict.remove id
Maybe -> identity
-- move' : Just ((Float,Float),Element) -> Form
move' (Just ((x,y), makebox)) = move (x,y) makebox
view : Model -> Element
view dict =
flow down
[ buttonAdd 10.0 20.0 --makes add & remove buttons
, collage 500 500 (List.map move' (Dict.values dict)) --draws the dict
]
input : Signal Event
input = merge
(Add <~ (Signal.subscribe add)) --pipes button channels into events
(Remove <~ (Signal.subscribe remove))
model : Signal Model
model = foldp update Dict.empty input
main : Signal Element
main = view <~ model
We still get the same, not very helpful type error. But now it's on the move'
function. I added the type signature I thought of in comments.
There are two problems in this piece of code:
move'
takes an Element
(among other things) and tries to move
it, but move
works on Form
s. So that requires a call to toForm
, before it works.Dict.values
gives a list of values, not a list of Just
values (of type Maybe.Maybe
).The solution is therefore a move'
function like so:
move' : ((Float,Float), Element) -> Form
move' (a,b) = move a (toForm b)