The page reviews the Haskell bindings for OpenCog.
You can find the main code in: /opencog/haskell
For in depth information on the implementation and project details: Haskell Bindings - GSoC 2015
For Haddock documentation: opencog-atomspace-0.1.0.0
To use the Haskell bindings, it is necessary to have installed:
- Stack (Haskell development tool - Stack wikipage)
To install Stack, you should follow Download instructions.
Or you can use the octool tool, installing dependencies (octool -d).
To check if you have proper ghc version installed. Run:
cd <ATOMSPACE_ROOT>/opencog/haskell stack setup
This will automatically build the haskell library.
If you want to use this library in some project you should include it to the package list on the project stack.yaml config file. For example:
... packages: - <ATOMSPACE_ROOT>/opencog/haskell ...
On the other hand, if you simply want to compile some code using this library, you should compile with:
export STACK_YAML=<ATOMSPACE_ROOT>/opencog/haskell/stack.yaml stack ghc example.hs
For using ghci:
export STACK_YAML=<ATOMSPACE_ROOT>/opencog/haskell/stack.yaml stack ghci
Or, to avoid defining STACK_YAML every time, you can include this library to your local environment, adding this library path to your package list in your local config file: ~/.stack/global/stack.yaml ,and then running:
stack install opencog-atomspace
Then you can compile simple .hs files with:
stack ghc example.hs
- It is necessary to previously build and install the AtomSpace, because the opencog-atomspace haskell library depends on the haskell-atomspace C wrapper library.
So, if you have a problem like "haskell-atomspace library not found" , first of all, you should ensure it was properly installed when installing the AtomSpace.
- If when running "stack ghc" or "stack build" you get an error about "Missing C library: haskell-atomspace", you should add the flag:
--extra-lib-dir=/usr/local/lib/opencog (with proper library location).
- If when running "stack ghci" you get an error about "lhaskell-atomspace not found", you should add the flags:
- If when using "stack ghci" you see that ghci is interpreting the code: "[..] Compiling ... (..., interpreted )"
Then, a better option is to compile the package to object code, so it is loaded, which runs faster. All you have to do is to execute only one time:
stack ghci --ghc-options -fobject-code
On future uses, ghci will automatically load the compiled package.
- If you find problems when building haskell libraries. One good option is to remove the directory:
It is automatically created when building, and sometimes becomes inconsistent.
Haskell bindings are composed of:
- atomspace-cwrapper: a shared library, C wrapper for the atomspace main class. It is built and installed like all the atomspace libraries.
- opencog-atomspace: a haskell package that links with the haskell-atomspace library and offers an API for haskell programming on the atomspace.
To use the opencog-atomspace haskell library, we just import the modules like:
import OpenCog.AtomSpace ...
You can find many examples in : /examples/haskell
To generate proper Haddock documentation on your own, you should go to the build directory and execute:
Then you can open the OpenCog documentation (build/doc/html/index.html), go to "OpenCog source code documentation - Libraries - Haskell bindings library" and click on the "opencog-atomspace" link.
NOTE: Documentation can be REALLY useful. There you can see the complete definition of Haskell bindings, including data types that are automatically generated by template haskell, and are not available in the code.
The main idea is to build programs that work on an AtomSpace on the Monad 'AtomSpace'.
Then, we can run this programs with the function runOnNewAtomSpace:
runOnNewAtomSpace :: AtomSpace a -> IO a
It creates a new C++ atomspace behind, does all the computation, and finally deletes it.
Note that AtomSpace is an instance of the type class: MonadIO.
So, we can lift IO actions inside the monad AtomSpace, through the use of liftIO.
import OpenCog.AtomSpace.Api import Control.Monad.IO.Class prog :: AtomSpace () prog = do liftIO $ putStrLn "hello world" ... main :: IO () main = runOnNewAtomSpace prog
The simplest option to work in an AtomSpace is to use runOnNewAtomSpace as mentioned before.
By doing that, you can work freely in the monad AtomSpace and you don't have to specify the atomspace instance everytime, because it is implicit.
But, sometimes, you want to work with multiples atomspaces, or maybe you want to do interactive evaluation using GHCi.
For that, you can create new AtomSpaces (from a optionally given parent atomspace) with the function:
newAtomSpace :: Maybe AtomSpaceObj -> IO AtomSpaceObj
To work over an atomspace, you can use the infix operator <:
(<:) :: AtomSpaceObj -> AtomSpace a -> IO a
main :: IO () main = do parentAS <- newAtomSpace Nothing childAS <- newAtomSpace (Just parentAS) parentAS <: insert (Node "ConceptNode" "GenConcept" noTv) childAS <: do insert (Node "ConceptNode" "PrivateConcept1" (stv 1 1)) insert (Node "ConceptNode" "PrivateConcept2" (stv 0.5 1)) parentAS <: program childAS <: debug parentAS <: remove (Node "ConceptNode" "GenConcept" noTv) program :: AtomSpace () program = do s <- get (Node "ConceptNode" "GenConcept" noTv) ...
Atom is the main data type to represent the different types of atoms.
Function to insert atoms to the atomspace. To create new atoms or just to update the mutable information of a specific atom.
insert :: Atom -> AtomSpace ()
Function to get an atom back from the atomspace (With updated mutable information).
get :: Atom -> AtomSpace (Maybe Atom)
Function to remove atoms from the atomspace.
remove :: Atom -> AtomSpace Bool
Function to show the given atom in opencog notation.
printAtom :: Atom -> IO ()
Debug function to print the state of the atomspace on stderr.
debug :: AtomSpace ()
Used to evaluate things like a SatisfactionLink. (Note: Before using it, you should insert the atom into the atomspace).
evaluate :: Atom -> AtomSpace (Maybe TruthVal)
Used to execute any kind of FunctionLink. (Note: Before using it, you should insert the atom into the atomspace).
execute :: Atom -> AtomSpace (Maybe Atom)