2
votes

Consider this code:

type Graph = (Char, Function) 
type Function = Char -> Int 
doThingsWithGraph :: Graph -> String
func :: Function 
graph :: Graph

main = do  x <- getChar
           y <- getChar
           let graph = (x, func)
           putStrLn $ doThingsWithGraph graph

The implementation of doThingsWithGraph does not matter for now. Now the issue here is that the func's output also depends on the second char I am getting from the user, but I have no idea how to pass it on to it. I can't pass it as an argument because func is implemented by third party and I can't change the type. So if haskell had global variables and y was one the func's implementation would look something like this:

func char 
       |isDigit char = digitToInt char + digitToInt y
       |otherwise    = digitToInt y

This obviously doesn't work because func has no idea what y is, but that's the idea of what it should do. So y is the value that I need somehow to let func know about (it is the one I'm getting from user in the second line of main). I can't do getLine inside func because that won't be consistent with data type which I can't change (part of the large framework). Any ideas? Maybe some helper function can replace func in let graph = (x, func)and then return the function of type Function? This is just a guess..

2
I'm not really sure what you mean by "func is implemented by third party". Do you mean "I want third parties to be able to implement such funcs"?Tom Ellis
Sorry I was misleading, I meant that "graph" is already implemented in a framework I am working with and requires a function of type Function as a second argument.ivanibash

2 Answers

5
votes

Your user generating func can simply implement a function like Char -> Function and hand you that instead of a raw Function with the promise that you'll give them the second char from input as that first argument.

Indeed, this is a very natural thing in a language with no globals: you must state all the information you need in your function inputs. Anything else just won't work.

You'll end up with

doThingsWithGraph (x, makeFunc y)

When that gets burdensome, the Reader Monad can help.

1
votes

I'm not really sure what you mean by "func is implemented by third party". Do you mean "I want third parties to be able to implement such funcs in a way that permits me to use them like this"?

If so, does

func :: Char -> Function
func y char 
       |isDigit char = digitToInt char + digitToInt y
       |otherwise    = digitToInt y

do the job? This is also what J. Abrahamson is suggesting, I think.