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
How do you define a function in Haskell? The most basic way of defining a function in Haskell is to “declare'' what it does. For example, we can write: double :: Int -> Int double n = 2*n. Here, the first line specifies the type of the function and the second line tells us how the output of double depends on its input.
In most imperative languages functions are called by writing the function name and then writing its parameters in parentheses, usually separated by commas. In Haskell, functions are called by writing the function name, a space and then the parameters, separated by spaces.
elem :: element -> list -> Bool. Use elem if you want to check whether a given element exists within a list.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With