I've done a Haskell library allowing to manipulate multivariate polynomials. It uses some instances defined by the numeric-prelude library, e.g. an additive group instance. The addition for this instance is denoted
in this library. I find this a bit annoying because there's already the usual
for numbers, so I defined:
import Algebra.Additive as AlgAdd
(^ ^) :: Polynomial a -> Polynomial a -> Polynomial a
(^ ^) p q = p AlgAdd. q
But it seems to me that by doing that, the "infix properties" of
are lost. I never dealt with the infix properties, and I have a couple of questions. I want to keep the same infix properties.
Looking at the code I see this line:
infixl 6 , -
This line is isolated, at the beginning of the code. So should I similarly include the line
infixl 6 ^ ^, ^-^
at the beginning of my code? In this blog post the author defines the infix property of a function just before defining this function. Is it another, equivalent way to proceed? And is it not possible to do something like (^ ^) = (AlgAdd. )
in such a way that the infix properties are automatically copied?
Still looking at the code, I see:
{-# MINIMAL zero, ( ), ((-) | negate) #-}
What does that mean?
I'm also wondering how to define the opposite of a polynomial. I have the substraction
p ^-^ q
but how to define^-^ p
?Finally, when the package author defines the instance e.g. for
Double
, he/she writes:instance C Double where {-# INLINE zero #-} {-# INLINE negate #-} {-# INLINE ( ) #-} {-# INLINE (-) #-} zero = P.fromInteger 0 negate = P.negate ( ) = (P. ) (-) = (P.-)
What is the purpose of INLINE
?
CodePudding user response:
You can write the infix declaration above the definition, but it's not a requirement.
infixl 6 ^ ^, ^-^ (^ ^) :: Polynomial a -> Polynomial a -> Polynomial a (^ ^) = (AlgAdd. )
The infix properties cannot be copied.
The
Minimal
pragma refers to the "minimal set of methods that must be defined" for a class definition to be total. In your case it means you can either write a definition for the methods "zero
and( )
and(-)
" or "zero
and( )
andnegate
" since you can definenegate
in terms of the first groupnegate a = zero - a
and
(-)
in terms of the second. So it doesn't matter which one you define.n - m = n negate m
Not sure.
The
Inline
pragma forces ghc to inline (unfold) the definition. Here is the answer to Is there ever a reason to not mark a monadic bind operator(>>=)
as inline?
CodePudding user response:
Without a fixity declaration, your operators ^ ^
and ^-^
will behave as if declared with
infixl 9 ^ ^, ^-^
that is, left-associative with extremely high precedence. If you want them to behave more or less like "regular" addition and subtraction, then you should explicitly declare them to have precedence level 6 with
infixl 6 ^ ^, ^-^
The associativity and precedence levels are not "transferable" from another operator; you'll just have to look up the behavior of the operator you want to be similar to and declare yours appropriately.