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