Skip to content

Instantly share code, notes, and snippets.

@jspahrsummers
Created July 15, 2012 01:15
Show Gist options
  • Save jspahrsummers/3114225 to your computer and use it in GitHub Desktop.
Save jspahrsummers/3114225 to your computer and use it in GitHub Desktop.
Hypothetical messaging primitive for Objective-Haskell
mutableStringWithString :: Id -> IO Id
mutableStringWithString str =
getClass "NSMutableString" <.> stringWithString str
arrayWithObjects :: [Id] -> IO Id
arrayWithObjects objs = do
getClass "NSArray" <.> arrayWithObjectsAndCount objs (length objs)
@jonsterling
Copy link

Furthermore, return x >>= blah is usually a pretty clear sign that you shouldn't be using monadic binding in the first place! In fact, what you want for that instance is just flip ($). So, dig this:

(@.) = flip ($)

concatNSStrings :: Id -> Id -> IO Id
concatNSStrings a b = 
    a @. stringByAppendingString b

@jspahrsummers
Copy link
Author

Right, but the @ was to solve the problem of a variadic application. Also, it could be written (@) if need be (to get around the infix restriction).

@jonsterling
Copy link

Yeah, still not necessary if you're going to put the receiver at the end. So, you could do

concatNSStrings :: Id -> Id -> IO Id
concatNSStrings a b = (@) a stringByAppendingString b

if you want, but it doesn't really make a difference. (@) is still just flip ($), with no bind in site. With currying, we have stopped caring about variadic nonsense.

@jspahrsummers
Copy link
Author

I'm talking about this case:

f obj a b =
    (@) obj >>= somethingWithTwoArguments a b

Unless I'm missing something, flip ($) can't do that.

@jonsterling
Copy link

Ah, gotcha. You still won't be able to use (@) as an alias for return, since infix operators have to take two arguments.

And flip ($) will work fine, because its function argument is partially applied; remember that function application binds tighter than infix operators. So, the following works:

(@.) = flip ($)

putFourStrings :: String -> String -> String -> String -> IO ()
putFourStrings a b c d = putStrLn a >> putStrLn b >> putStrLn c >> putStrLn d

"fourth" @. putFourStrings "first" "second" "third"
-- first
-- second
-- third
-- fourth

(In addition: the very fact that return x >>= f a b c can do what you want it to indicates that x @. f a b c can do the same. In fact, the two are provably equivalent).

@jspahrsummers
Copy link
Author

Hmm, interesting. I'll make sure to add that. Thanks!

@jspahrsummers
Copy link
Author

So, this works for the example you gave, and for any Id -> … function, but it doesn't seem to work for IO Id -> …:

mutableStringWithString :: Id -> IO Id
mutableStringWithString str = (getClass "NSMutableString") @. stringWithString str

Is there some way to make an <@.> operator for lifting + applying + joining?

@jonsterling
Copy link

Yep! But you don't need to make a new operator. It's called (>>=). ;-)

mutableStringWithString str = 
    getClass "NSMutableString" >>= stringWithString str

@jspahrsummers
Copy link
Author

That appears to drop str into the self position of stringWithString, though.

@jonsterling
Copy link

Nope. Remember, we're putting the receiver last.

@jspahrsummers
Copy link
Author

You're right. Sorry, I've been hopping back and forth between a few different mental models today.

@jonsterling
Copy link

;) no worries

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment