我在玩自定義運算子,infix,infixl和infixr。現在我很困惑。
我已經為串列乘法撰寫了一個自定義運算子,并認為將其宣告為一個沒有方向關聯性的簡單中綴運算子,將自動提供兩種情況nr * list和list * number,因為它們可以隨意互換。
import Prelude hiding ((*))
infix 6 *
(*) :: Int -> [a] -> [a]
n * l = if n < 0 then []
else 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沒有方向結合性,是可交換的,可以寫成(a b) c, a (b c), b a c, (b a) c, 等等...
對于我的示例,與 以及所有其他組合2 * [1, 2] * 1相同1 * (2 * [1, 2]),所以我真的不明白,為什么即使使用不同型別的運算元,也沒有對可交換運算子宣告進行隱式整形。
uj5u.com熱心網友回復:
固定性宣告僅影響決議,而不影響運算子的定義。
如果使用infixl,a * b * c則被決議為(a * b) * c。
如果使用infixr,a * b * c則被決議為a * (b * c)。
如果您使用infix,那么您是說a * b * c無法決議;您必須使用括號來指定您的意思是(a * b) * c還是a * (b * c)。比較
Prelude> infix 6 ***; (***) = ( )
Prelude> 1 *** 2 *** 3
<interactive>:8:1: error:
Precedence parsing error
cannot mix ‘***’ [infix 6] and ‘***’ [infix 6] in the same infix expression
Prelude> infixl 6 ***; (***) = ( )
Prelude> 1 *** 2 *** 3
6
在您的情況下,*不是完全關聯的,因為型別不對齊。它可以是右關聯的,因為型別檢查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))
)
你對結合性和交換性的理解是錯誤的。“非關聯”不是“可交換”的同義詞。事實上,這兩個屬性是正交的:一個給定的算子可以是兩者,或者兩者都不是,或者只是兩者之一。
整數加法是結合的和可交換的。
整數減法既不是結合的也不是可交換的。
矩陣乘法是結合的,但不是可交換的。(
BA可能與AB完全不同甚至未定義。)NAND 操作(邏輯與的否定)是可交換的,但不是結合的:
(True NAND True) NAND False == False NAND False == True True NAND (True NAND False) == True NAND True == False
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/389035.html
