1

下面的代码应该产生一个按钮,当按下它时会创建一个框(以及一个用于移除框的按钮)

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

但是,它会产生这种类型的错误:

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

我看不到这个错误来自哪里, Maybe.Maybe 被传递到哪里update,我该如何解决?

4

1 回答 1

1

TL;博士

查找并替换带有collage调用的行main

                            , collage 500 500 (List.map (\((x,y), makebox) -> move (x,y) (toForm makebox))

快速代码清理

这是很多代码。我不得不稍微改变一下风格才能理解它是如何工作的。我所做的是将更多的函数移到顶层并给它们类型注释。我还将button_add/更改remove为 camelCase,因为这是标准的 Elm 命名约定。这是结果:

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

我们仍然得到相同的,不是很有帮助的类型错误。但现在它在move'功能上。我在评论中添加了我想到的类型签名。

问题

这段代码有两个问题:

  1. move'接受一个Element(除其他外)并尝试move它,但move适用于Forms。所以这需要调用toForm, 在它工作之前。
  2. 这就是类型错误的来源:Dict.values给出一个值列表,而不是一个Just值列表(类型Maybe.Maybe)。

因此,解决方案是这样的move'函数:

move' : ((Float,Float), Element) -> Form
move' (a,b) = move a (toForm b)
于 2015-02-06T13:16:09.173 回答