【问题标题】:How do I define infix functions in Haskell?如何在 Haskell 中定义中缀函数?
【发布时间】:2013-03-11 19:37:53
【问题描述】:

我想将函数定义为中缀,这样用户就不必手动在函数周围加上反引号来调用它。具体来说,我正在编写一个类似 DSL 的函数,该函数接受 Rank 和 Suit 并构建扑克牌记录:

-- pseudocode
data PokerCard = PokerCard { rank :: Rank, suit :: Suit } deriving (Eq)

of :: Rank -> Suit -> PokerCard
r of s = PokerCard { rank = r, suit = s }

pokerDeck = [
  Ace of Spades,
  Two of Spades,
  ...
  ]

我相信of 被保留为case ... of 表达式的语法,所以我必须将其重命名为of'.of+of 等。

【问题讨论】:

标签: function haskell infix-notation


【解决方案1】:

没有办法用字母数字名称作为中缀来定义函数。 Haskell 的语法规则只允许使用符号名称或用反引号包围的函数名称作为中缀 - 没有办法改变它。

【讨论】:

    【解决方案2】:

    好吧,您可能已经知道这一点,但是(当然)运算符 / 可以 / 是中缀。所以你可以,而不是r of sr >| s

    【讨论】:

    • 确实,运算符必须是中缀的。
    • @dave4420 除非你用括号括起来。
    • @sepp2k 当然,但这在道德上与将字母数字标识符包装在反引号中相同。您不能定义前缀符号运算符(除非您在使用它的任何地方将其包裹在括号中),就像您无法定义中缀字母数字运算符(除非您在使用它的任何地方将其包裹在反引号中)。
    【解决方案3】:

    这是一个带有一些额外输入但没有反引号的 hacky 解决方案!我首先在reddit上发布了这个,如果可以的话。

    我假设您已经为Rank 派生了Enum

    data OF = OF
    ace :: OF -> Suit -> PokerCard
    ace _ s = PokerCard Ace s
    
    -- or point-free
    two :: OF -> Suit -> PokerCard
    two _ = PokerCard Two
    
    -- or with const
    three :: OF -> Suit -> PokerCard
    three = const (PokerCard Three)
    
    -- you get the idea!
    -- the rest in one line:
    four,five,six,seven,eight,nine,ten,jack,king :: OF -> Suit -> PokerCard
    [four,five,six,seven,eight,nine,ten,jack,king] = map (const . PokerCard) [Four .. King]
    
     -- now you can write
     pokerDeck = [
       ace OF Spades, two OF Spades -- and so on
       ]
    

    OF 数据类型不是绝对必要的,但可以防止混淆(但非常金属)的东西,例如 ace "Motorhead" Spades。你仍然可以写ace undefined Spades,我认为真的没有办法。

    如果of 不是关键字,你甚至可以写成of = OF


    还有一个非常邪恶的技巧可以完全摆脱“of”,并使用数字作为卡片:

    {-# LANGUAGE FlexibleInstances #-} -- this goes on top of your file
    
    instance Num (Rank -> Suit) where
      fromInteger n = (undefined : map Card[Ace .. King]) !! (fromInteger n)
    

    现在2 Spades :: Card 类型检查(但您需要显式类型!)并且是您认为的 :-) 但是,我强烈建议您不要在严肃的代码中这样做;但它看起来有点酷。

    【讨论】:

      猜你喜欢
      • 2017-08-15
      • 2012-08-04
      • 2015-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多