我正在尝试将foldp与结合两个信号的输入函数的结果一起使用。
这是我的代码。
import Graphics.Element (..)
import Graphics.Collage (..)
import Color (..)
import Signal
import Keyboard
import Text (asText)
import Time (..)
-- Display
render : (Int, Int) -> Element
render (xDiff, yDiff) = collage 200 200 [
rotate (degrees (toFloat yDiff))
(filled blue (ngon 5 (10 * toFloat xDiff))) ]
-- Combine two signals to be a pair
input = Signal.map2 (,) (fps 25) Keyboard.arrows
-- Fold past combined signals from input and pass resulting signal to render
main : Signal Element
main = Signal.map render
(Signal.foldp (\dir (upd, {x, y}) ->
(x + dir.x, y + dir.y)) (0,0) input)
-- Fold past Keyboard.arrows and pass resulting signal to render
--main : Signal Element
--main = Signal.map render
-- (Signal.foldp (\dir (x, y) ->
-- (x + dir.x, y + dir.y)) (0,0) Keyboard.arrows)
我得到的错误是:
Type mismatch between the following types on line 34, column 55 to 60:
(Float, { x : Int, y : Int })
{ a | x : Int, y : number }
It is related to the following expression:
input
Type mismatch between the following types on line 34, column 26 to 46:
{ a | x : Int, y : number }
number
Looks like something besides an Int or Float is being used as a number.
It is related to the following expression:
(x + dir.x,y + dir.y)
Type mismatch between the following types on line 34, column 26 to 46:
Int
{ a | x : number, y : number }
It is related to the following expression:
(x + dir.x,y + dir.y)`
在主要方面,我可以用asText替换render并得到类似的错误,因此我认为即使渲染处理输入可能存在问题,我也认为我与foldp一起使用的功能也存在问题。
最佳答案
TL; DR
这是main
的正确代码:
main : Signal Element
main = Signal.map render
(Signal.foldp (\(upd, dir) (x, y) ->
(x + dir.x, y + dir.y)) (0,0) input)
寻找解决方案
您的类型有问题。因此,让我们看一些类型:
foldp : (a -> b -> b) -> b -> Signal a -> Signal b
input : Signal (Float, {x : Int, y : Int})
render : (Int, Int) -> Element
main : Signal Element
在
main
的定义内,问题似乎源于foldp
,因此让我们在foldp
的上下文中使main
的类型更具体。 render
映射到输出上,因此b
应该是(Int, Int)
,它与(0,0)
初始值相对应。 a
应该类似于输入。因此,对于main中的特定foldp
,您具有:foldp : ((Float, {x : Int, y : Int}) -> (Int, Int) -> (Int, Int)) -- the function
-> (Int, Int) -- the initial value
-> Signal (Float, {x : Int, y : Int}) -- the input
-> Signal (Int, Int) -- the output
好的,所以我们知道
foldp
的函数参数应该具有哪种类型。但是当前函数有什么错误类型?(\dir (upd, {x, y}) -> (x + dir.x, y + dir.y)) : {recordExt1 | x : number, y : number'} -> (something, {recordExt2 | x : number, y : number'}) -> (number, number')
嗯..看起来太复杂了。让我们简化一些假设。
*我们可能不需要扩展记录,因此请使用
recordExt1 = recordExt2 = {}
。*两个
number
可能是Int
。* something是具有
x
和y
记录的元组中的第一个,因此必须是Float
信号中的input
。-- simplified type of inline function
{ x : Int, y : Int} -> (Float, { x : Int, y : Int}) -> (Int, Int)
-- function deduced from specialised `foldp` type
(Float, {x : Int, y : Int}) -> (Int, Int) -> (Int, Int)
那些看起来相似。该函数的第一个和第二个参数已交换,第二个参数应为整数的元组,而不是具有整数
x
和y
的记录。回顾
您可以看到注释中
main
的另一个定义如何起作用,但是随后您将(x,y)
更改为{x,y}
,并在错误的参数周围添加了(upd,
... )
。最后一点
如果您实际上并未计划使用
fps 25
中的时间增量,则还可以使用:input = Signal.sampleOn (fps 25) Keyboard.arrows
main = Signal.map render
(Signal.foldp (\dir (x, y) ->
(x + dir.x, y + dir.y)) (0,0) input)
这给您几乎相同的行为。