alexgordon has quit [Quit: Computer has gone to sleep.]
<joelteon>
ugh this project makes me feel unclean
<joelteon>
I have a Tryable instance for IO, StateT s IO, and ExceptionP ... IO
sharkbot has quit [Remote host closed the connection]
sharkbot has joined #elliottcable
Sgeo has quit [Quit: No Ping reply in 180 seconds.]
Sgeo has joined #elliottcable
eligrey has quit [Quit: Leaving]
cloudhead has joined #elliottcable
cloudhead has quit [Ping timeout: 245 seconds]
cloudhead has joined #elliottcable
wudofyr has quit [Remote host closed the connection]
wudofyr has joined #elliottcable
wudofyr has quit [Remote host closed the connection]
wudofyr has joined #elliottcable
yorick has joined #elliottcable
Sorella has joined #elliottcable
Sorella has joined #elliottcable
cloudhea1 has joined #elliottcable
cloudhead has quit [Ping timeout: 264 seconds]
eligrey has joined #elliottcable
cloudhea1 has quit [Ping timeout: 245 seconds]
jesusabdullah has joined #elliottcable
<jesusabdullah>
knew I was forgetting somethin'
<joelteon>
you were bitch
<jesusabdullah>
that's right!
alexgordon has joined #elliottcable
<joelteon>
so guys
<jesusabdullah>
so
<joelteon>
I just used RankNTypes and NoMonomorphismRestriction in a module
<joelteon>
for an actual reason
<joelteon>
how many points is that
<joelteon>
I think it's 50
<alexgordon>
joelteon: -50 for making your code unreadable to 90% of programmers!
<alexgordon>
joelteon: just think what ec's score is
<jesusabdullah>
dangit joelteon that's not javascript
<jesusabdullah>
for shaaame
<joelteon>
ok
<joelteon>
so it's +50 for being cool
<joelteon>
-50 for being too cool
<joelteon>
i broke even again
<alexgordon>
joelteon: wtf is a monomorphism restriction anyway
<jesusabdullah>
lol
<purr>
lol
<alexgordon>
joelteon: hm. read the wiki on it, don't understand what purpose it serves
<alexgordon>
why not just include a type signature lol
<joelteon>
ok, well, see
<joelteon>
I have a logger helper function
<joelteon>
logInfo
<joelteon>
and it needs to fetch the current time and do other IO, but it also needs to be agnostic about what monad it's acting in
<joelteon>
because I'm using both the generic MonadIO m and ExceptionP ... SafeIO, which is pipes-safe's wrapper monad
<joelteon>
so I defined a helper logWith :: (forall a. Monad m => IO a -> m a)
<joelteon>
err
<joelteon>
so I defined a helper logWith :: (forall a. Monad m => IO a -> m a) -> Text -> m ()
<joelteon>
oh whoops
<joelteon>
one more try
<joelteon>
so I defined a helper logWith :: Monad m => (forall a. IO a -> m a) -> Text -> m ()
<joelteon>
there we go, much better
<joelteon>
because inside the body of logWith, it applies the function it receives, f, to IO actions that have different return types
<alexgordon>
man I hate haskell sometimes
<alexgordon>
lol
<purr>
lol
<joelteon>
time <- f getZonedTime
<joelteon>
f $ putStrLn logMessage
<joelteon>
and so you see
<joelteon>
if I made it just take (IO a -> m a), the type would be restricted to (IO ZonedTime -> m ZonedTime)
<joelteon>
and putStrLn x obviously doesn't have the type IO ZonedTime
<joelteon>
the forall allows f to be polymorphic within the body of logWith
<joelteon>
NoMonomorphismRestriction prevents logInfo and logInfoIO from both trying to act inside MonadIO m, because SafeIO isn't a MonadIO instance obviously
<joelteon>
all logWith knows about f is that it can transform IO actions into actions inside the monad it actually wants
<alexgordon>
-_-
<joelteon>
honestly it's amazing the compiler is capable of this
<alexgordon>
joelteon: "just because you *can*, doesn't mean you *should*"
<joelteon>
well
<joelteon>
it definitely makes generalizing log easier
cloudhead has joined #elliottcable
<joelteon>
ok i have a question here
<joelteon>
for each client/server pair, there's a thread handling reading from the client and one reading from the server
<joelteon>
if I encounter an exception during either, I have this function isRetryable that detects whether I can retry connecting to the client or the server
<joelteon>
but I use it twice
<joelteon>
once inside the client's Proxy
<joelteon>
and once outside, once the client has terminated, I check whether the error is retryable
<joelteon>
because when the client Proxy throws an exception, the parent thread catches it and returns it as Left
<joelteon>
readloop -> exception -> propogates to parent thread, which handles showing messages
<joelteon>
because the parent thread is the one who knows how to cleanly restart everything, but the parent thread *shouldn't* be concerned with displaying messages to the user
<joelteon>
I could make an ADT that wraps an Exception, I guess
<joelteon>
Retryable e or NonRetryable e
<joelteon>
and then don't bother checking within the parent thread
<joelteon>
but then both the client thread and the server thread are gonna be using isRetryable
yorick has quit [Remote host closed the connection]
<joelteon>
hm
<joelteon>
I dunno, what SHOULD I do
<joelteon>
I can't just return Left ex because there's some exception-related short circuiting in pipes-safe, I have to rethrow it