Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I parameterise my Haskell functions?

I hope my terminology is correct here - if not, feel free to edit anything.

I'm using Haskell as a helper-language whilst writing a paper on combinatorial game theory - i.e., all of my functions just juggle numbers and help me to come to a solution for the game I'm studying.

I wrote all of the functions for a concrete, integral 'board size' (think chequerboard, 5x5 etc). I wanted to expand to study boards of any size, so modified all the relevant functions by including an Integer parameter. e.g.,

type Size = Int

squares :: Size -> [Square]
squares size = [ (x,y) | x <- [1..size],  
                         y <- [1..size]]

This, however, has started to get messy. Functions which normally I would consider size-independent have to be supplied with a Size whenever they access a function which requires a Size.

This very quickly leads to lines like this:

reaching size = (losing size) \\\ (setA size)

takeUDmir _  []       = []
takeUDmir size (x:xs) = [x] ++ takeUDmir size (xs \\\ mirUD size x)

rotate size s = concatMap (mirUD size) (mirLR size s)

(Note that the content of the functions really doesn't matter, I'm just trying to show how out-of-hand it has become.)

I'm pretty confident using Haskell, and with functional programming in general, but I've got no idea how I could go about removing all of these size references, and simply relying on something else which sets the size for each function which requires its use.

I think I'm probably looking for a monad, but I've got no idea.

like image 809
Allan Avatar asked Dec 28 '13 23:12

Allan


People also ask

Are all functions in Haskell curried?

In Haskell, all functions are considered curried: That is, all functions in Haskell take just one argument. This is mostly hidden in notation, and so may not be apparent to a new Haskeller.

Can a Haskell function return nothing?

No. However, you can have functions that return a trivial value.


1 Answers

This is a perfect time to pull out the Reader monad—it abstracts the notion of some globally available, read-only configuration data.

data Config = Config { size :: Int, ... }

type MyMonad = Reader Config

fun :: MyMonad Result
fun = funNeedingTheSize <$> asks size <*> pure arg1 <*> pure arg2

runMyMonad :: Config -> MyMonad a -> a
runMyMonad = flip runReader
like image 132
J. Abrahamson Avatar answered Sep 22 '22 07:09

J. Abrahamson