Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement this function in Haskell

Tags:

haskell

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 
like image 786
mentics Avatar asked Sep 10 '11 17:09

mentics


People also ask

How do you declare a function in Haskell?

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.

How do I run a function in Haskell?

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.

How do you check if something is in a list Haskell?

elem :: element -> list -> Bool. Use elem if you want to check whether a given element exists within a list.


2 Answers

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.

like image 147
nominolo Avatar answered Nov 06 '22 06:11

nominolo


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.

like image 5
Joey Adams Avatar answered Nov 06 '22 07:11

Joey Adams