榆树信号和类型注释

时间:2014-11-03 06:26:16

标签: signals elm

来自榆树新手但长时间使用Haskeller,这是一个快速查询。

目标:在地图上有指定位置的城镇地图,我想检查用户点击是否靠近城镇,并确定该城镇。

所以,我像往常一样收集信号:

clickPositionsSignal = sampleOn Mouse.clicks Mouse.position

给了我一个元组,我想把它变成一个Int(表示最近的城镇的数量)。城镇被指定为

positions : [Position] 
type Position = {number : Int, x : Int, y : Int}

执行此操作的功能是:

whichTown : (Int,Int) -> Int
whichTown (x,y) = 
            let pz = map (\p -> getDistance p.x p.y x y) positions |> head
            in pz.number

现在,我需要将此功能应用于我的clickPositionsSignal。

查看各种示例,我修改了一些代码......

whichLocationSignal : Signal Int
whichLocationSignal =           
      let wbl (x,y) = whichTown(x,y)
      in wbl <~ clickPositionsSignal

....这有效。我得到了最近的城镇的数量。

但这绝对是麻烦和重复的。问题是为什么我不能简单地写:

whichLocationSignal = whichTown clickPositionsSignal

该行引发多个类型错误,我还没有足够的经验来解释

1 个答案:

答案 0 :(得分:1)

TL; DR

应该是:

whichLocationSignal = whichTown <~ clickPositionsSignal

whichLocationSignal = lift whichTown clickPositionsSignal

(你已经弄明白了)

如何读取类型错误

因此,提供这些类型错误的完整版代码将是:

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

我得到的类型错误是:

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

我承认,这些类型错误令人困惑 (你甚至可能会说它们是不正确的。我只能说这就是你得到的当前类型错误的质量,抱歉!)
当Elm的类型错误没有意义时,一个基本的提示是看你在翻转期望/实际时是否更有意义。那么第一种类型的错误就没有意义了。但第二个提供了一些信息:clickPositionsSignal某种程度上预计会有Int类型,而不是某些Signal。连同第三条错误消息一起开始有意义:whichTown做了另一种方式,应该给出Int,但你得到Signal ...
此时,您可以找到这两者的用法,一旦您注意到whichTown适用于(Int,Int)clickPositionsSignal : Signal (Int,Int),您就会发现错误并且编译器消息会产生某种影响弯曲的感觉。

上述修复方法是使用lift : (a -> b) -> Signal a -> Signal b将功能(whichTown)“提升”到Signal“级别”。大多数人更喜欢使用中缀运算符<~