我正在尝试使用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)`
在main中我可以用asText替换render并得到类似的错误,所以我认为即使渲染处理输入可能存在问题,我认为我使用foldp的函数也存在问题。
答案 0 :(得分:3)
以下是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
个。
*某个元组是元组中的第一个,其记录为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,
... {{ 1}}围绕错误的论点。
如果您实际上没有计划使用)
的时间增量,您还可以使用:
fps 25
这给你几乎相同的行为。
答案 1 :(得分:1)
即使有了Apanatshka的优秀答案,当我从foldp
调用更新函数时,我对参数的交换感到困惑,所以这里有一个小小的文章来澄清:
module Foldp2 where
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))) ]
-- `input` produces a (Float, Record)-Tuple wrapped in a Signal
input : Signal (Float, {x : Int, y : Int})
input = Signal.map2 (,) (fps 25) Keyboard.arrows
-- define an update function operating on the unwrapped `input` function
-- `foldp` will make it work on the wrapped `input'
update : ( Float, {x:Int, y:Int}) -> (Int, Int) -> (Int, Int)
update (upd, dir) (x,y) = (x + dir.x, y + dir.y)
-- Making the type of 'foldp' applied to 'update' explicit:
-- Notice that the order of arguments compared to `update` is swapped.
-- The swapping, I think, was the origin of confusion for OP (mine indeed it was).
folding : (Int, Int) -> Signal (Float, {x:Int, y:Int}) -> Signal (Int, Int)
folding = Signal.foldp update
-- Further notice that "aligning" the arguments in `update` with those of
-- `folding` by:
-- update : (Int, Int) -> ( Float, {x:Int, y:Int}) -> (Int, Int)
-- update (x,y) (upd, dir) = (x + dir.x, y + dir.y)
-- gives error:
-- Type mismatch between the following types on line 26, column 28 to 48:
-- { x : Int, y : Int }
-- number
-- It is related to the following expression:
-- (x + dir.x,y + dir.y)
-- unless you `flip` the order arguments in `folding`:
-- folding : (Int, Int) -> Signal (Float, {x:Int, y:Int}) -> Signal (Int, Int)
-- folding = Signal.foldp (flip update)
main : Signal Element
main = Signal.map render (folding (0,0) input)