Types 将信号int与int[Elm]进行比较时出现类型错误
我想在选中时突出显示一个按钮(浅蓝色背景)。为此,我编写了以下代码:Types 将信号int与int[Elm]进行比较时出现类型错误,types,signals,elm,Types,Signals,Elm,我想在选中时突出显示一个按钮(浅蓝色背景)。为此,我编写了以下代码: players : Input Int players = input 1 playerSelection : Element playerSelection = flow right [ color (buttonPressed 1) (button players.handle 1 "Solo") , color (buttonPressed 2) (button players.handle 2
players : Input Int
players = input 1
playerSelection : Element
playerSelection = flow right [
color (buttonPressed 1) (button players.handle 1 "Solo")
, color (buttonPressed 2) (button players.handle 2 "2P")
, color (buttonPressed 3) (button players.handle 3 "3P")
, color (buttonPressed 4) (button players.handle 4 "4P")
]
buttonPressed : Int -> Color
buttonPressed p = if players.signal == p then lightBlue else white
当我在代码的其余部分运行此命令时,会收到以下错误消息:
if | players.signal == p -> lightBlue
| True -> white
Expected Type: Int
Actual Type: Signal.Signal Int
问题是players.signal是一个signal Int。如果我将它替换为一个正常的数字,我的程序就会正常工作。但是,我需要一个按钮在选中时变为浅蓝色,在选中另一个按钮时变为白色。有没有办法将信号转换为正常整数进行比较?我曾尝试创建一个外部比较方法并将信号提升到该方法,但该方法的结果将是一个我无法使用的信号布尔。为了说明我所做的:
buttonPressed : Int -> Color
buttonPressed p = if equals p <~ players.signal then lightBlue else white
equals : Int -> Int -> Bool
equals a b = a == b
我大致知道会出什么问题。一个函数发送两个信号,它只需要一个。老实说,我更愿意看到信号传播到一个更相关的位置,比如beginState:
beginState : Element
beginState = collage 600 600 [
move (0,270) (toForm (playerSelection <~ players.signal))
]
beginState:Element
beginState=拼贴600[
移动(0270)(toForm(玩家选择回答“更新”)
我认为的页面上有一些很好的资源,可以回答您提出的一般问题:
我将试着做一个简短的回顾并补充我的观点,因为这些只是官方文件的链接
类型错误注释
首先,来自Elm编译器的类型错误可能会令人困惑。预期的与实际的类型错误通常以非直观的顺序给出。但是您得到的类型错误来自于给foldp
一个作为信号的基值。foldp的类型:(a->b->b)->b->Signal a->Signal b
显示如果b
=信号元素
,则foldp
的结果是信号(Signal b)
。这通常是当您开始在代码中“太早”使用信号时出现的问题
我知道你认为信号是可变变量,只想在你想要其当前值的任何地方提及它们。但正如你所指出的,这基本上就是信号不同于可变变量的地方。因此,简单架构的总体思路是将所有输入组合成一个数据结构:
data Input =
Players Int
| Control String
input : Signal Input
input = merge (Players <~ players.signal) (Control <~ control.signal)
这基本上就是第一个链接中描述的常见模式。我想这回答了您的问题:如何存储和传递信号中的信息?:使用foldp
它回答了玩家的位置。信号
适合我的代码,而不将我的所有信号支撑到main?因为这里的答案是:你必须将所有信号支撑到main
。但是这个答案不令人满意,可能无法扩展,所以我包含了第二个链接
单个foldp
保存所有状态的模式似乎有点过于严格。1但它是有效的。除非您开始扩大它,并希望对不同组件的关注点进行一些分离
因此,架构页面的基本思想是通过在模块中定义它们的状态、输入、更新和视图来创建不交互的组件。然后主程序导入不同的模块,创建数据结构来组合不同的状态/输入/更新/视图,并最终能够再次使用单个foldp
e在main
中
1我实际上认为它太严格了,可以放宽,但这是我不想讨论的一个切点。这不是一个琐碎的想法,如果要实施的话,还需要做更多的工作,所以这并不完全适合新手参考。但这是我最喜欢的项目(不是因为我有时间),所以你可以这样做:
“更新”前的原始答案
总体思路
你的想法是正确的。这个想法是把播放器从按钮按下的功能中完全取出。对于信号的一般建议是尽量不要使用它们,然后在最后一刻在主中使用它们。如果主变得太复杂,那么即使at意味着在其他函数中使用信号。但尝试仅从非信号函数开始
解决方案
仅在main中使用一个信号,以便使用播放器。按下按钮中的信号
需要将其作为参数传递(注意参数是Int
,而不是signal Int
):
您需要将此Int
从playerSelection
传递到按钮按下
,因此也将其添加为参数:
playerSelection : Int -> Element
playerSelection ps = flow right [
color (buttonPressed ps 1) (button players.handle 1 "Solo")
, color (buttonPressed ps 2) (button players.handle 2 "2P")
, color (buttonPressed ps 3) (button players.handle 3 "3P")
, color (buttonPressed ps 4) (button players.handle 4 "4P")
]
现在您可以这样编写main:
main = playerSelection <~ players.signal
main=playerSelection元素
playerSelection ps=向右流动[
颜色(按按钮的ps 1)(按钮播放器。手柄1“单独”)
,颜色(按钮按下的ps 2)(按钮播放器手柄2“2P”)
,颜色(按钮按下的ps 3)(按钮播放器手柄3“3P”)
,颜色(按钮按下的ps 4)(按钮播放器手柄4“4P”)
]
按下按钮:Int->Int->Color
按钮按下ps p=如果ps==p,则为浅蓝色,否则为白色
main=playerSelection感谢您结构化的回答。不幸的是,我无法得出相同的结果。我编辑了我的原始帖子,以展示我对如何存储和传递信号信息的附加问题所做的工作。非常感谢您的帮助!BabyBurger,我刚刚编辑了我的答案。我希望这是我的答案这是你最新的问题。
main = view <~ foldp update initialState input
buttonPressed : Int -> Int -> Color
buttonPressed ps p = if ps == p then lightBlue else white
playerSelection : Int -> Element
playerSelection ps = flow right [
color (buttonPressed ps 1) (button players.handle 1 "Solo")
, color (buttonPressed ps 2) (button players.handle 2 "2P")
, color (buttonPressed ps 3) (button players.handle 3 "3P")
, color (buttonPressed ps 4) (button players.handle 4 "4P")
]
main = playerSelection <~ players.signal
import Graphics.Input (Input, input, button)
players : Input Int
players = input 1
playerSelection : Int -> Element
playerSelection ps = flow right [
color (buttonPressed ps 1) (button players.handle 1 "Solo")
, color (buttonPressed ps 2) (button players.handle 2 "2P")
, color (buttonPressed ps 3) (button players.handle 3 "3P")
, color (buttonPressed ps 4) (button players.handle 4 "4P")
]
buttonPressed : Int -> Int -> Color
buttonPressed ps p = if ps == p then lightBlue else white
main = playerSelection <~ players.signal