2025-01-16 17:10:42 -06:00
2025-02-25 14:59:23 -06:00
2025-01-14 02:24:54 -06:00
2025-02-13 00:38:21 -06:00
2025-01-16 13:14:08 -06:00
2025-02-25 01:32:12 -06:00
2025-02-25 14:17:29 -06:00
2025-02-25 14:59:23 -06:00
2025-02-11 17:05:16 -06:00
2025-02-25 14:28:18 -06:00
2025-02-25 14:59:04 -06:00

HushGP

A PushGP implementation in Haskell

Tasks

  • Post minimal core of exec to haskell discourse for advice about speed optimization.
  • Do test-driven development on this one.
    • Write tests for every function.
    • tests/ are just copied from make-grade, need to write for this project.
    • Included examples of basic assertions, QuickCheck, Hspec, hspec-quickcheck.

Design considerations

The biggest design constraint is that for the exec stack (but not data stacks) we have to be able to detect type at runtime.

A simple way to do this for the exec stack is as a list of custom data type. That custom Gene data type must have as many sub-types as there are types + fuction types.

If the input stack is singular, then it needs a general Gene data type, but if there was an input stack per type, they could be specific.

I would really like to benchmark some of the following three versions for speed:

  1. Where some functions can act on all stacks (this repo), and thus every data stack is a list of a more general Gene type, elements of which are wrapped in data TypeGene so they can be identified in stack-general functions. To bind all the stacks for convenience, we could put each stack list in a tuple, or a custom data type, Data.Map or Data.HashMap. The exec stack will always need a more general Gene type, with Gene types wrapping each individual thing, for runtime identification.

  2. Where type-specific functions act on each stack independently, and thus each data stack can have exclusive specific basic types, which are not wrapped in data TypeGene, because they do not need to be identified. To bind all the stacks for convenience, we could put each stack list in a tuple, or a custom data type, but not in a or Data.Map or Data.HashMap, as those require homogenous (K, V) pairs. The exec stack will always need a more general Gene type, with Gene types wrapping each individual thing, for runtime identification.

  3. Alternatively, for the exec stack, we could store strings, and eval strings (similar to my custumized version of propel clojure) Regular and input stacks can stil be either TypeGene or basic types. This is clearly not ideal.

  4. For the exec stack itself, typeable, data generic, ghc.generic, data.dynamic, heterogeneous lists, etc. could also help, to detect the type of variables at runtime, but I would rather stick to language basics at first.

Nix Users

This took my machine about 2 hours to build the environment after running nix develop.

Description
PushGP in Haskell
Readme 750 KiB
Languages
Haskell 99%
Nix 0.7%
Makefile 0.3%