2

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"? Commented Oct 26, 2013 at 19:29
  • 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. Commented Oct 26, 2013 at 19:38

2 Answers 2

5

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.

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

4 Comments

So you are saying that I can make a function which takes one argument and returns a function which takes something else? If that's the case that is what I need. I just never wrote a function that returns a function before. Do you have any further tips how to implement this? Thanks!
Exactly. makeFunc would be of Char -> Char -> Int type, meaning you can either pass two Char arguments and get an Int or just one argument and get a Char -> Int function. No extra steps are needed.
@user2922609 That's exactly right! And a really common pattern in Haskell. It's strange at first, no doubt, but you can see all multi-parameter functions as being "applied one argument at a time". For instance if we have add x y = x + y then add :: Int -> Int -> Int and add 2 :: Int -> Int both being perfectly valid functions. This property is called "partial application".
See also haskell.org/haskellwiki/Currying, which explains more about this technique of "functions returning functions".
1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.