繁体   English   中英

在 Haskell 中定义自定义运算符的关联性

[英]Defining the associativity of a custom operator in Haskell

我正在使用自定义运算符infixinfixlinfixr 现在我很困惑。

我为列表乘法编写了一个自定义运算符,并认为将其声明为没有方向关联性的简单中缀运算符会自动提供nr * listlist * number这两种情况,因为它们可以随意互换.

import Prelude hiding ((*))

infix 6 *

(*) :: Int -> [a] -> [a]
n * l
    | n < 0     = []
    | n == 1    = l
    | otherwise = l ++ (n - 1) * l

现在, 3 * [1, 2, 3] [1, 2, 3, 1, 2, 3, 1, 2, 3] ,但是[1, 2, 3] * 3抛出错误,因为我从未明确定义list * nr

我的问题:中infix的独特功能是什么,为什么不总是使用中infixl或中infixr ,因为它应该没有区别?


我将“无方向关联性”/中infix理解为“可交换”的同义词:

a + b + c has no directional associativity or is commutative and can be written as (a + b) + c , a + (b + c) , b + a + c , (b + a) + c , and so on ...

对于我的示例2 * [1, 2] * 11 * 2 * [1, 2]以及所有其他排列相同,所以我真的不明白为什么对交换运算符声明没有隐式重塑,即使使用不同类型的操作数。

固定性声明仅影响解析,而不影响运算符的定义。

如果使用infixl ,则a * b * c被解析为(a * b) * c

如果您使用infixr ,则a * b * c被解析为a * (b * c)

如果您使用infix ,那么您是在说a * b * c无法解析; 必须使用括号来指定您的意思是(a * b) * c还是a * (b * c)

在您的情况下, *不是完全关联的,因为类型不对齐。 它可以是右关联的,因为3 * (6 * [])类型检查但不是左关联的,因为(3 * 6) * []没有。 使用中infix ,您不允许3 * 6 * [] 如果您使用infixr ,那么您可以编写它,解析器会将其视为3 * (6 * [])


使这样的可交换运算符很棘手,因为在类型级别它们是两个不同的运算符。 这很容易定义:

-- Ignoring the fact that both of these operators are already
-- used by the Applicative class for different purposes.

(*>) :: Int -> [a] -> [a]
0 *> l = []
n *> l = l ++ (n-1) * l

(<*) :: [a] -> Int -> [a]
(<*) = flip (*>)

*作为Int -> [a] -> [a][a] -> Int -> [a]工作是很棘手的,如果不是不可能的话。 (也许涉及多参数类型族?

-- Compiles, but does not run. Not sure why...
{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, FlexibleContexts #-}

class Multiplable x y where
  type Result x y
  (***) :: x -> y -> Result x y

instance Multiplable Int [a] where
   type Result Int [a] = [a]
   0 *** l = []
   n *** l = l ++ ((n - 1) *** l)

instance Multiplable [a] Int where
  type Result [a] Int = [a]
  l *** 0 = []
  l *** n = l ++ (l *** (n - 1))

)


您对关联性和交换性的理解是不正确的。 “不结合”不是“交换”的同义词。 事实上,这两个属性是正交的:给定的运算符可以是两者,也可以不是,或者只是两者之一。

  • Integer 加法是关联和交换的。

  • Integer 减法既不结合也不可交换。

  • 矩阵乘法是关联的,但不是可交换的。 BA可以与AB不同,甚至完全未定义。)

  • 与非运算(逻辑与的否定)是可交换的,但不是结合的:

     (True NAND True) NAND False == False NAND False == True True NAND (True NAND False) == True NAND True == False

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM