3

我想将一个函数定义为中缀,这样用户就不必手动用反引号包围该函数来调用它。具体来说,我正在编写一个类似 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等。

4

3 回答 3

10

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

于 2013-03-11T19:41:10.063 回答
6

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

我假设你已经导出Enum了 for Rank

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类型检查(但您需要显式类型!)并且是您认为的那样:-) 但是,我强烈建议您不要在严肃的代码中这样做;但它看起来很酷。

于 2013-03-11T21:27:37.113 回答
6

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

于 2013-03-11T20:03:22.270 回答