```{-# LANGUAGE DataKinds #-}

{-|
Module: CSA
Description: Connectivity description using connection-set algebra
Maintainer: jensegholm@protonmail.com
Stability: experimental

This module uses connection-set algebra to describe connectivity between
two entities with a scalar ('Double') value. The library build on the concept
of M. Djurfeldt's Connection-Set Algebar [1].
The connection expressions can be compiled to a dependently typed
'AdjacencyMatrix' from the "Numeric.LinearAlgebra.Static" package. Such
a matrix can be used and exported as a regular n-dimensional vector.

Usage:

>>> toAdjacencyMatrix None :: L 2 2
(matrix
[ 0.0, 0.0
, 0.0, 0.0 ] :: L 2 2)

>>> toAdjacencyMatrix \$ Minus (AllToAll 2) (OneToOne 1) :: L 2 2
(matrix
[ 1.0, 2.0
, 2.0, 1.0 ] :: L 2 2)

1: Mikael Djurfeldt. The Connection-set Algebra: a formalism for the
representation of connectivity structure in neuronal network models,
implementations in Python and C++, and their use in simulators,
BMC Neuroscience, 2011. https://doi.org/10.1186/1471-2202-12-S1-P80
-}
module CSA where

import GHC.TypeLits
import Numeric.LinearAlgebra.Static

-- | An adjacency matrix describing connections in a directed graph

-- | An expression algebra tree (AST) that describes connections
--   between two elements
data Expr
= None -- ^ An empty connection (only 0s)
| AllToAll ℝ -- ^ Full connectivity with the given value
| OneToOne ℝ -- ^ One-to-one (diagonally) connectivity
| Mask (ℝ -> ℝ -> ℝ) -- ^ A masked connectivity given by a function
| Plus Expr Expr -- ^ Addition of two connectivity expressions
| Minus Expr Expr -- ^ Subtraction of two connectivity expressions

-- | Converts an expression to an adjacency matrix by unrolling the
--   expression tree from left to right