module ProjectM36.DataTypes.NonEmptyList where
import ProjectM36.Base
import qualified Data.Map as M
import qualified Data.HashSet as HS
import ProjectM36.AtomFunctionError
import ProjectM36.DataTypes.List
nonEmptyListAtomType :: AtomType -> AtomType
nonEmptyListAtomType arg = ConstructedAtomType "NonEmptyList" (M.singleton "a" arg)
nonEmptyListTypeConstructorMapping :: TypeConstructorMapping
nonEmptyListTypeConstructorMapping = [(ADTypeConstructorDef "NonEmptyList" ["a"],
[DataConstructorDef "NECons" [DataConstructorDefTypeVarNameArg "a",
DataConstructorDefTypeConstructorArg (ADTypeConstructor "List" [TypeVariable "a"])]])]
nonEmptyListLength :: Atom -> Either AtomFunctionError Int
nonEmptyListLength (ConstructedAtom "NECons" _ (_:nextCons:_)) = do
c <- listLength nextCons
pure (c + 1)
nonEmptyListLength (ConstructedAtom "NECons" _ _) = pure 1
nonEmptyListLength _ = Left AtomFunctionTypeMismatchError
nonEmptyListHead :: Atom -> Either AtomFunctionError Atom
nonEmptyListHead (ConstructedAtom "NECons" _ (val:_)) = pure val
nonEmptyListHead _ = Left AtomFunctionTypeMismatchError
nonEmptyListAtomFunctions :: AtomFunctions
nonEmptyListAtomFunctions = HS.fromList [
AtomFunction {
atomFuncName = "nonEmptyListLength",
atomFuncType = [nonEmptyListAtomType (TypeVariableType "a"), IntAtomType],
atomFuncBody = AtomFunctionBody Nothing (\(nonEmptyListAtom:_) ->
IntAtom . fromIntegral <$> nonEmptyListLength nonEmptyListAtom)
},
AtomFunction {
atomFuncName = "nonEmptyListHead",
atomFuncType = [nonEmptyListAtomType (TypeVariableType "a"), TypeVariableType "a"],
atomFuncBody = AtomFunctionBody Nothing (\(nonEmptyListAtom:_) -> nonEmptyListHead nonEmptyListAtom)
}
]