8

Wonderful thing about Haskell. The type of a function almost dictates its implementation. That's the case for this one, but... my brain just isn't wrapping around the nested function thing here:

mkDyn :: (Typeable a) => ((a -> IO()) -> IO ()) -> ((Dynamic -> IO()) -> IO ())

The only question is how to handle error handling in the fromDynamic call that will be required, but... I can deal with that once I have the rest figured out. I'm guessing there will need to be something like the following somewhere. But I can't seem to get the wrapper lambda stuff figured out.

case fromDynamic x of
  Just x -> f x
  Nothing -> undefined -- TODO 
2
  • 1
    Wow, I didn't even know Haskell had dynamic type support, let alone that it was available in base. Learn something new every day. Commented Sep 10, 2011 at 17:49
  • @Joey IIRC there is even a library to write imperative-style code with easy assignment operators, but I forgot where. I think it was mentioned once on Planet Haskell. Commented Sep 10, 2011 at 20:38

2 Answers 2

10

I think you want toDyn, not fromDynamic. So let's do this slowly:

mkDyn :: Typeable a =>
         ((a -> IO ()) -> IO ())
      -> (Dynamic -> IO ())
      -> IO ()
mkDyn k f = ...

Our return type should be IO () and we can obtain that either by calling k or f. Calling f doesn't help us much, because we would somehow materialise a Dynamic, but we cannot do that (sensibly) from k. So we want to call k. k needs another function as its argument, so lets start like this:

mkDyn k f = k (\a -> ...)

So the function's argument is Typeable a => a -> IO (). We don't have a function of that type, but we have a function of type Dynamic -> IO (). Because of the Typeable constraint we can use toDyn to turn our a into Dynamic and get:

mkDyn k f = k (\a -> f (toDyn a))

There are simpler implementations (e.g., return () or k (\a -> return ()), but this one appears to make sense.

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

4 Comments

@rampion Two can play that game! mkDyn = (. (. toDyn)).
I tend to prefer the pointed versions. I only use point-free style if things are truly just a simple pipeline. Anything (even slightly) more complicated and I would regret it the next time I read the code.
@Daniel Wagner using sections for function composition, twice? I think my brain just exploded a little.
I love stackoverflow, especially for Haskell questions. Brilliant, and thank you!
5

I cheated and used the Djinn program.

I first generalized the type given:

f :: (a -> c)
  -> ((a -> b) -> b)
  -> ((c -> b) -> b)

The (a -> c) represents the toDyn function function, and c represents Dynamic. b represents IO ().

Djinn's result was surprisingly simple:

@djinn (a -> c) -> ((a -> b) -> b) -> ((c -> b) -> b)
f a b c = b (\ d -> c (a d))

Making it more specific (by replacing the (a -> c) with the toDyn function), we get:

mkDyn :: (Typeable a) => ((a -> IO()) -> IO ()) -> ((Dynamic -> IO()) -> IO ())
mkDyn b c = b (\ d -> c (toDyn d))

which matches nominolo's answer.

1 Comment

Does this prove that nominolo is a djinn?

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.