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?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.