榆树中的神秘类型错配

时间:2015-02-06 11:53:10

标签: user-interface dictionary types 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

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的哪个位置,我该如何解决?

1 个答案:

答案 0 :(得分:1)

TL; DR

查找&amp;将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适用于Form。因此,在它工作之前需要调用toForm
  2. 这是类型错误的来源:Dict.values提供值列表,而不是Just值列表(类型Maybe.Maybe)。
  3. 因此,解决方案是move'函数,如下所示:

    move' : ((Float,Float), Element) -> Form
    move' (a,b) = move a (toForm b)