module Mind ( NeuronIndex (..) , getNeuronIndex , Edge (..) , Network (..) , createEmptyNetwork , connectNeurons ) where import Data.Ix -- index different neuron types data NeuronIndex = Input Int | Internal Int | Output Int deriving (Show, Eq) getNeuronIndex :: NeuronIndex -> Int getNeuronIndex (Input i) = i getNeuronIndex (Internal i) = i getNeuronIndex (Output i) = i -- define incident edges newtype Edge = Edge (NeuronIndex, Float) deriving (Show, Eq) -- define networks data Network = Network { numInput :: Int , internalNeurons :: [[Edge]] , outputNeurons :: [[Edge]] } deriving (Show, Eq) -- create a completely empty network createEmptyNetwork :: Int -> Int -> Int -> Network createEmptyNetwork i h o = Network i (replicate h []) (replicate o []) -- connect two neurons together with a new edge connectNeurons :: Network -> NeuronIndex -> NeuronIndex -> Float -> Maybe Network -- internal sink connectNeurons (Network i h o) source (Internal sink) weight = if (validSource (Network i h o) source) then do newH <- insertEdge h sink $ Edge (source, weight) return $ Network i newH o else Nothing -- output sink connectNeurons (Network i h o) source (Output sink) weight = if (validSource (Network i h o) source) then do newO <- insertEdge o sink $ Edge (source, weight) return $ Network i h newO else Nothing -- connectNeurons _ _ (Input _) _ = Nothing -- helpers for connectNeurons -- check if a given NeuronIndex can be used as a valid source validSource :: Network -> NeuronIndex -> Bool validSource _ (Output _) = False validSource (Network i _ _) (Input x) = if (inRange (0, i) x) then True else False validSource (Network _ h _) (Internal x) = if (inRange (0, length h) x) then True else False -- insert a new edge into a neuron list, possibly failing insertEdge :: [[Edge]] -> Int -> Edge -> Maybe [[Edge]] insertEdge ns i e | (inRange (0, length ns) i) = let (front, es:back) = splitAt i ns in Just $ front ++ [e:es] ++ back | otherwise = Nothing