I'm not sure if a Markov Chain generator is the proper term for this, really all it does is create the chain, it doesn't generate any text from it. The code is below, and I'd appreciate any feedback: bad practices, code smells, poor naming, anything at all really.
module Main where
import Data.List(find, delete)
type Chain = [Node]
data Node = Node {nPrefix :: String, nSuffixes :: [String]} deriving (Show, Eq, Read)
generateChain :: Int -> [String] -> Chain
generateChain n = foldl (learnSample n) []
learnSample :: Int -> Chain -> String -> Chain
learnSample n chain sample = foldl learnGroup chain groups
where groups = (groupings (n+1) . words) sample
learnGroup :: Chain -> [String] -> Chain
learnGroup chain group =
case find (\node -> nPrefix node == prefix) chain of
Just node -> delete node chain ++ [Node prefix (nSuffixes node ++ [suffix])]
Nothing -> chain ++ [Node prefix [suffix]]
where
prefix = unwords $ init group
suffix = last group
groupings :: Int -> [a] -> [[a]]
groupings n list
| length list >= n = take n list : groupings n (drop 1 list)
| otherwise = []
main :: IO ()
main = print $ generateChain 1 ["a b a b a c a d"]