0

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.

  1. 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?

  1. Still looking at the code, I see:

    {-# MINIMAL zero, (+), ((-) | negate) #-} 

What does that mean?

  1. I'm also wondering how to define the opposite of a polynomial. I have the substraction p ^-^ q but how to define ^-^ p?

  2. 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?

1
  • 1
    Questions 2, 3, and 4 should be asked separately. Commented Jul 29, 2022 at 20:59

2 Answers 2

3
  1. 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.

  2. 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 (+) and negate" since you can define negate in terms of the first group

    negate a = zero - a 

    and (-) in terms of the second. So it doesn't matter which one you define.

    n - m = n + negate m 
  3. Not sure.

  4. 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?

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you. For 3) I mean there is the substraction, as for numbers, x - y, and there is the opposite - x = 0 - x. I'm wondering how to define the 'opposite' operator?
The opposite operator would be negate wouldn't it? Normally an operator takes two argument so that wouldn't be a operator unless you use the PostfixOperators extension. This lets you define (-.) = negate written parenthesised: (x -.).
Yes, this is negate. Thanks again.
Re: (3) the negation operation -foo is special built-in syntax; it's not possible for users to define their own prefix operators. You can use RebindableSyntax to give it a different meaning, but you can only have one meaning per module that way.
2

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.