I'm trying to learn a bit of Haskell by writing a small set of functions for computations over finite (Galois) fields. Years ago I wrote the first version of a similar library for the computer algebra system GNU Maxima (see here) and I thought I'd try the same thing with Haskell.
However, I'm getting myself all muddled with data types. For a finite field, you need a base prime q (the characteristic of the field), and a polynomial p(x) which is irreducible modulo q. If p(x) has degree n, then the order of the field is q^n and its elements are all polynomials (modulo q) with degree n-1 or less.
We can represent polynomials as lists of their coefficients, so that elements of the field are simply lists (or vectors, if you prefer) of elements of Z_q and of length n. Addition is done component-wise modulo q, and multiplication is done modulo p(x).
I reckon if I can get the data type and addition sorted out the rest will be straightforward. My first attempt is this:
import Data.List
data GF = GF {characteristic::Int
,power::Int
,poly::[Int]
,irreducible::[Int]
} deriving(Eq, Show)
The power element is unnecessary - it is after all simply one less than the length of the irreducible polynomial - but it's a convenience to have it rather than having to compute it.
Then I had my addition function as:
addGF :: GF -> GF -> GF
addGF x y = GF q n zp p
where
q = characteristic x
n = power x
zp = zipWith (\i j -> rem (i+j) q) xp yp
where
xp = poly x
yp = poly y
p = irreducible x
This works, but is inelegant, and I'm sure very "un-Haskell-ish". Part of the problem is that I don't know how to decouple the definition (or type) of a Galois field from its elements.
What I need to do is to provide a general type for a field, and on top of that define elements of it. There are, after all, things I might want to do with a field which are independent of its elements, such as generate a normal basis, find a primitive element, generate a table of logarithms for a primitive element, generate random elements, etc.
So I guess my question is: how do I define a generic type of a Galois field, in such a way that operations on its elements are as natural as possible?
I have read a number of pages about defining data types, classes, etc, and I've no doubt that one of them contains the solution to my problem. But the more I read the more confused I become. All I want is for somebody to point me gently but firmly in the right direction. Thanks!