module Main where

import System.Random.MWC
import Control.Monad.Primitive


nouns = ["man", "ball", "woman", "table"]

verbs = ["hit", "took", "saw", "liked"]

articles = ["a", "the"]

newtype Noun  = Noun String
                deriving Eq

newtype Article = Article String
                  deriving Eq

newtype Verb = Verb String
               deriving Eq

instance Show Noun where
  show (Noun s) = s

instance Show Article where
  show (Article s) = s

instance Show Verb where
  show (Verb s) = s

newtype NounPhrase = NounPhrase (Article,Noun)
                  deriving (Eq)

instance Show NounPhrase where
  show (NounPhrase (a,n)) = (show a) ++ " " ++ (show n)

newtype VerbPhrase = VerbPhrase (Verb,NounPhrase)
                  deriving Eq

instance Show VerbPhrase where
  show (VerbPhrase (v, np)) = (show v) ++ " " ++ (show np)

data Sentence = Sentence (NounPhrase,VerbPhrase)
                deriving Eq

instance Show Sentence where
  show (Sentence (np,vp)) = (show np) ++ " " ++ (show vp)



uniformW :: PrimMonad m => [String] -> (String -> a) -> Gen (PrimState m) -> m a
uniformW list datacon st = do
  i <- uniformR (0, (length list) - 1) st
  return $ datacon (list !! i)

{- A possibly stupid way of generating random sentences is making all of them instances of Variate type class.
Then, we are able to create sentences.

Only problem:  uniformR is not defined for our type.
-}

uniformP :: (PrimMonad m , Variate b) =>  (b -> a) -> Gen (PrimState m) -> m a
uniformP datacon st = do
  v <- uniform st
  return $ datacon v
  
instance Variate Noun where
  uniform = uniformW nouns Noun
  uniformR = undefined

instance Variate Verb where
  uniform = uniformW verbs Verb
  uniformR = undefined

instance Variate Article where
  uniform = uniformW articles Article
  uniformR = undefined


instance Variate NounPhrase where
  uniform   =   uniformP NounPhrase
  uniformR = undefined
  
instance Variate VerbPhrase where
  uniform = uniformP VerbPhrase
  uniformR = undefined

instance Variate  Sentence where
  uniform = uniformP Sentence
  uniformR = undefined


genSentence :: IO Sentence
genSentence = do
  randomState <- createSystemRandom
  sentence <- (uniform randomState)
  return sentence
