I found this code in the unm-hip package. So Pixel is a function ?
class Imageable i where
type Pixel i :: *
rows :: i -> Int
cols :: i -> Int
ref :: i -> Int -> Int -> (Pixel i)
makeImage :: Int -> Int -> PixelOp (Pixel i) -> i
pixelList :: i -> [Pixel i]
pixelList i = [ ref i r c | r <- [0..(rows i - 1)], c <- [0..(cols i - 1)]]
It's merely an infix synonym for fmap , so you can write e.g. Prelude> (*2) <$> [1.. 3] [2,4,6] Prelude> show <$> Just 11 Just "11" Like most infix functions, it is not built-in syntax, just a function definition. But functors are such a fundamental tool that <$> is found pretty much everywhere.
In general terms, where f and g are functions, (f . g) x means the same as f (g x). In other words, the period is used to take the result from the function on the right, feed it as a parameter to the function on the left, and return a new function that represents this computation."
() is very often used as the result of something that has no interesting result. For example, an IO action that is supposed to perform some I/O and terminate without producing a result will typically have type IO () .
in goes along with let to name one or more local expressions in a pure function.
As an extension to standard Haskell, you can deal with "kinds". Kinds are sort of a very basic type system for types and type constructors. Kind *
is a simple type, like Int
. Kind * -> *
is a type constructor that takes a type and yields a type, like Maybe
: pass it a type like Int
as an argument, and you get the type Maybe Int
.
The other extension used in this code (which I didn't notice at first, since the indentation was lost) is associated types. A typeclass in standard Haskell can specify a number of functions that the type must support. With associated types, it can additionally specify types and type constructors that are associated with the type.
Here, this means that a type i
that is an instance of Imageable
(i.e. behaves like an image) must have an associated pixel type Pixel i
, and this must be a simple type (kind *
), not a type constructor.
"So Pixel is a function?"
Pixel is a type-level function. It takes a single type (which must be an instance of Imageable) and returns a type of kind '*'. Based on it's usage in the example code, the input type must also be of kind '*'. So, Pixel is very much like Maybe, they are both "type constructors" of kind '* -> *', you provide them a "simple type" and they return a "simple type". They are also valid in the same locations. Just like you can't have a function of type 'Foo -> Maybe', you also won't be able to have a function of type 'Bar -> Pixel'.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With