Dynamically find out instances of classes (plugin system for haskell)

Hi, Is there any plugin system for haskell? For example, in Java, I can load all compiled classes from given directory, check their interfaces and run some methods through reflection etc. Is it possible in haskell, to load modules from given directory, and if in module there is instance of class then return instantiation of that class? I hope this is understandable what I'm trying to achieve here. Thank you, Radek. -- Codeside: http://codeside.org/ Przedszkole Miejskie nr 86 w Lodzi: http://www.pm86.pl/

From: haskell-cafe-bounces@haskell.org [mailto:haskell-cafe-bounces@haskell.org] On Behalf Of Radoslaw Grzanka
Hi, Is there any plugin system for haskell? For example, in Java, I can load all compiled classes from given directory, check their interfaces and run some methods through reflection etc. Is it possible in haskell, to load modules from given directory, and if in module there is instance of class then return instantiation of that class?
There are two libs that I'm aware of. http://hackage.haskell.org/cgi-bin/hackage-scripts/package/plugins-1.0 http://hackage.haskell.org/cgi-bin/hackage-scripts/package/metaplug-0.1. 1 AFAICT, plugins is more mature and has a higher-level API, but the last time I looked it was not working on Windows under ghc >= 6.6 (can anyone refute or verify this?) It's more like dynamic linking than Java's reflection: you have to already know what functions are in the module (and their types) to be able to call them. I'm not sure about directly creating values of data types exported from the module. Alistair ***************************************************************** Confidentiality Note: The information contained in this message, and any attachments, may contain confidential and/or privileged material. It is intended solely for the person(s) or entity to which it is addressed. Any review, retransmission, dissemination, or taking of any action in reliance upon this information by persons or entities other than the intended recipient(s) is prohibited. If you received this in error, please contact the sender and delete the material from any computer. *****************************************************************

Hi, Thanks for answer.
There are two libs that I'm aware of.
http://hackage.haskell.org/cgi-bin/hackage-scripts/package/plugins-1.0
http://hackage.haskell.org/cgi-bin/hackage-scripts/package/metaplug-0.1. 1
Unfortunatly former needs gcc, latter does not compile . I will have to install msys or something I guess
It's more like dynamic linking than Java's reflection: you have to already know what functions are in the module (and their types) to be able to call them. I'm not sure about directly creating values of data types exported from the module.
I know the types - not a problem. I just don't know the names. Thanks, Radek.

Bayley, Alistair-2 wrote:
There are two libs that I'm aware of.
http://hackage.haskell.org/cgi-bin/hackage-scripts/package/plugins-1.0
http://hackage.haskell.org/cgi-bin/hackage-scripts/package/metaplug-0.1. 1
There is also http://hackage.haskell.org/cgi-bin/hackage-scripts/package/hint-0.1 I managed to install it (though not without some hassle, i.e. having to use multiple Cabal versions), and make simple examples work. -- Grzegorz -- View this message in context: http://www.nabble.com/Dynamically-find-out-instances-of-classes-%28plugin-sy... Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.

Hello Radoslaw, Thursday, November 22, 2007, 11:34:56 AM, you wrote:
Is there any plugin system for haskell? For example, in Java, I can
there is also ghc-as-a-library shortly said, ghc doesn't have dynamic abilities, so providing features you need without compiling the whole program on the fly is hardly possible -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

Is there any plugin system for haskell? For example, in Java, I can load all compiled classes from given directory, check their interfaces and run some methods through reflection etc. Is it possible in haskell, to load modules from given directory, and if in module there is instance of class then return instantiation of that class?
I hope this is understandable what I'm trying to achieve here.
not really: the only classes in haskell are type classes, and if there is any class instance missing at compile time, you won't even get to runtime, so you don't have to worry about loading instances at runtime!-) perhaps you could describe the problem you are trying to solve, rather than the solution you would like to see? in general, ghci and hugs allow you to browse your modules, find out types and names, run tests, etc. ghci can be scripted to some extent (not always comfortably, but possibly sufficient if you only want to find and run all functions named test*, for instance), and if that isn't enough, ghc has an api that allows you to program your own variant of ghci, among other things. claus

2007/11/22, Claus Reinke
Is there any plugin system for haskell? For example, in Java, I can load all compiled classes from given directory, check their interfaces and run some methods through reflection etc. Is it possible in haskell, to load modules from given directory, and if in module there is instance of class then return instantiation of that class?
I hope this is understandable what I'm trying to achieve here.
not really: the only classes in haskell are type classes, and if there is any class instance missing at compile time, you won't even get to runtime, so you don't have to worry about loading instances at runtime!-)
Maybe I wasn't clear enough, maybe It is too much OO, maybe this is exploiting language, maybe there are better ways. ;) Let's say that in common module I have declaration (written from head, so may not compile - only for illustration) class Foo a where fun :: a -> String This is my interface declaration. Now in seperate modules I have: data GreatFooInstance = GreatFooInstance instance Foo GreatFooInstance where fun a = "1" in another module I have data GreatFooInstance' = GreatFooInstance' instance Foo GreatFooInstance' where fun a = "2" at my main program I want to load all modules from directory and receive a structure of (lack of vocabluary here) instantiated instances of the class like this: l :: Foo a => [a] l = [GreatFooInstance, GreatFooInstance'] This above is illegal in haskell I believe, so some other approach should be taken. The question is what is correct way (if any) to handle this. But if it was legal then the usage might be like: o = map foo l I cannot be more specifc because this is just theory, I'm playing with haskell to know it features and limits. The key here is to add and remove modules and find the list of modules at runtime, load it and (with known interface) call its functions. Hope it is clear enough now. Thanks, Radek.

the standard way to do that is use an existential wrapper: (This needs -fglasgow-exts or some flags)
module Main where
class Interface x where withName :: x -> String
data A = A String
instance Interface A where withName (A string) = "< Interface A with " ++ string ++ " >"
data B = B Int
instance Interface B where withName (B int) = "< Interface B with " ++ show int ++ " >"
data WrapInterface where WrapInterface :: forall z. Interface z => z -> WrapInterface
a :: A a = A "seven"
b :: B b = B 7
listOfWrapInterface :: [WrapInterface] listOfWrapInterface = [ WrapInterface a , WrapInterface b , WrapInterface (A "()") , WrapInterface (B (-2007)) ]
nameOfWrapped :: WrapInterface -> String nameOfWrapped (WrapInterface q) = withName q
instance Interface WrapInterface where withName = nameOfWrapped
main = do putStrLn (show (map nameOfWrapped listOfWrapInterface)) putStrLn (show (map withName listOfWrapInterface))
In ghci this prints: *Main> main ["< Interface A with seven >","< Interface B with 7 >","< Interface A with ()
","< Interface B with -2007 >"] ["< Interface A with seven >","< Interface B with 7 >","< Interface A with () ","< Interface B with -2007 >"]

ChrisK
the standard way to do that is use an existential wrapper:
Does this relate to the "basket of fruit" problem in object oriented languages? You created the existential wrapper to allow a multimorphic list type? -- _jsn

Jason Dusek wrote:
ChrisK
wrote: the standard way to do that is use an existential wrapper:
Does this relate to the "basket of fruit" problem in object oriented languages?
You created the existential wrapper to allow a multimorphic list type?
When you access the wrapped data then *_ONLY_* thing you can do with it is via the type class(es) that the GADT was wrapping. The example I gave had a single type class:
data WrapInterface where WrapInterface :: forall z. Interface z => z -> WrapInterface
One could have multiple interfaces:
data WrapInterface where WrapInterface :: (Interface z,Show z,Num z) => z -> WrapInterface
One could have more than one piece of data, note that WrapInterface takes three parameters:
data WrapInterface where WrapInterface :: Interface z => z -> z -> z -> WrapInterface
One could do both:
data WrapInterface where WrapInterface :: (Interface z1, Show z2,Num z3) => z1 -> z2 -> z3 -> WrapInterface
And so on. You can even write something like:> data WrapInterface' where
WrapInterface' :: a -> (a->String) -> WrapInterface'
listExample = [ WrapInterface' "Hello" (show . (++ "World")) , WrapInterface' 17 (show . succ) , WrapInterface' True (show . not) ]
apply :: WrapInterface' -> String apply (WrapInterface' item function) = function item
main = do putStrLn (show (map apply listExample))
Now a WrapInterface' holds item "a" and a function "a->String". When you unwrap this in a case statement you can then apply the function to the item to get the String. The output in ghci is: *Main> main ["\"HelloWorld\"","18","False"] -- Chris

Claus Reinke wrote:
I hope this is understandable what I'm trying to achieve here.
not really: the only classes in haskell are type classes, and if there is any class instance missing at compile time, you won't even get to runtime, so you don't have to worry about loading instances at runtime!-)
perhaps you could describe the problem you are trying to solve, rather than the solution you would like to see?
In [gasp!] Java, you can just stick compiled files into a folder, and write your main program such that ts scans this folder, loads anything it finds, and executes specific code within it. In other words, an instant plugin system. I imagine this is what the original poster is after. I'm not 100% sure, but I think hsplugins can dynamically load compiled *.o files in this way. Not sure whether this requires the person running the main program to have GHC installed though. Unlike Java, there's no reflection capabilities. This isn't too bad though; just write your own class definition to allow your main program to query the thing it just loaded and find out what it offers. class Describable d where available_functions :: d -> [FunctionInfo] data FunctionInfo = FunctionInfo {name :: String, description :: String, ...} Unlike general reflection (where you try to guess things from function names and so on), this can be taylored to exactly the kind of plugins you're trying to write.

I'm not 100% sure, but I think hsplugins can dynamically load compiled *.o files in this way. Correct.
Not sure whether this requires the person running the main program to have GHC installed though. Yes, it does.
Thanks && ciao, Leif
Unlike Java, there's no reflection capabilities. This isn't too bad though; just write your own class definition to allow your main program to query the thing it just loaded and find out what it offers.
class Describable d where available_functions :: d -> [FunctionInfo]
data FunctionInfo = FunctionInfo {name :: String, description :: String, ...}
Unlike general reflection (where you try to guess things from function names and so on), this can be taylored to exactly the kind of plugins you're trying to write.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

In [gasp!] Java, you can just stick compiled files into a folder, and write your main program such that ts scans this folder, loads anything it finds, and executes specific code within it. In other words, an instant plugin system. I imagine this is what the original poster is after.
dynamic class loaders used to be a favourite question mark in java type safety investigations. the wonderful thing is that it has long been known how to integrate orthogonal persistence (anything can be made to persist for as long as needed, including features like storing/retrieving functions into/from long-term storage) in languages with first-class procedures/functions, as well as how to integrate dynamic type checks for dynamic loading into otherwise static type system. even how to integrate that old research on persistence and type Dynamic into a type system as complex as haskell's has been investigated, and i believe that current clean does support both Dynamic and orthogonal persistence (there called first-class i/o, because it removes haskell's restriction of i/o to chars and bytes). there have been various projects trying to integrate full Dynamics or better persistence into haskell, but none have survived, as far as i know. the most recent one might be glasgow distributed haskell (if you can distribute everything between haskell processes on different machines, you can run one process as a persistence server) - i don't know what state that is in? there are various clever tricks to get much of Dynamic without special language support, and several implementation hacks to support at least dynamic loading of haskell code (see previous references in this thread). but while i mean hack in the best sense here, the latter are is still unsafe (lacking proper foundations in an extended type system, they circumvent the type system to achieve their aims; even ghci does that behind the scenes). not being fully integrated into language and implementations, these hacks are also notoriously brittle, not working on all platforms, or breaking with each compiler upgrade, etc. to cut a long, sad story short: dynamic loading is possible, but not well supported. if you do depend on the existing workarounds, expect to go through a lot of trouble, especially if you expect to maintain your code over more than one compiler version/platform. it doesn't help to see all those wonderful papers that remind us of what is possible in demonstrator projects, when those things no longer even build a year later, or on your platform.. anyone willing to have yet another go at this, properly, without temporary workarounds?-) the problem is that all the academic credit has been taken by earlier projects, so what is left is a lot of hard work and fiddly details, and by the time you've finished "porting clean's Dynamics and first-class i/o to haskell", your favourite haskell implementations will have moved on and left your patches behind. just like glasgow parallel and distributed haskell always seem to lag behind ghc by about a full version.. perhaps, if the haskell-to-clean translators ever gather enough momentum, there'd be at least one haskell implementation supporting these things? please, someone tell me that i'm too pessimistic, and that haskell, the language, will have orthogonal persistence and full Dynamic in the near future!-) claus
participants (9)
-
Andrew Coppin
-
Bayley, Alistair
-
Bulat Ziganshin
-
ChrisK
-
Claus Reinke
-
Grzegorz Chrupala
-
Jason Dusek
-
Leif Frenzel
-
Radosław Grzanka