hint-0.9.0.8: A Haskell interpreter built on top of the GHC API

Safe Haskell | Safe-Inferred
Language | Haskell2010

Language.Haskell.Interpreter

Contents

- The interpreter monad transformer
  - Running the interpreter
  - Interpreter options
  - Context handling
  - Module querying
  - Annotations
  - Type inference
  - Evaluation
- Error handling
- Miscellaneous

Synopsis

- class (MonadIO m, MonadMask m) => MonadInterpreter m where
  - fromSession :: FromSession m a
  - modifySessionRef :: ModifySessionRef m a
  - runGhc :: RunGhc m a
- data InterpreterT m a
- type Interpreter = InterpreterT IO
- runInterpreter :: (MonadIO m, MonadMask m) => InterpreterT m a -> m (Either InterpreterError a)
- data Option m a
- data OptionVal m = forall a. (Option m a) := a
- get :: MonadInterpreter m => Option m a -> m a
- set :: MonadInterpreter m => [OptionVal m] -> m ()
- languageExtensions :: MonadInterpreter m => Option m [Extension]
- availableExtensions :: [Extension]
- data Extension
  - = OverlappingInstances
  - | UndecidableInstances
  - | IncoherentInstances
  - | DoRec
  - | RecursiveDo
  - | ParallelListComp
  - | MultiParamTypeClasses
  - | MonomorphismRestriction
  - | FunctionalDependencies
  - | Rank2Types
  - | RankNTypes
  - | PolymorphicComponents
  - | ExistentialQuantification
  - | ScopedTypeVariables
  - | PatternSignatures
  - | ImplicitParams
  - | FlexibleContexts
  - | FlexibleInstances
  - | EmptyDataDecls
  - | CPP
  - | KindSignatures
  - | BangPatterns
  - | TypeSynonymInstances
  - | TemplateHaskell
  - | ForeignFunctionInterface
  - | Arrows
  - | Generics
  - | ImplicitPrelude
  - | NamedFieldPuns
  - | PatternGuards
  - | GeneralizedNewtypeDeriving
  - | ExtensibleRecords
  - | RestrictedTypeSynonyms
  - | HereDocuments
  - | MagicHash
  - | TypeFamilies
  - | StandaloneDeriving
  - | UnicodeSyntax
  - | UnliftedFFITypes
  - | InterruptibleFFI
  - | CApiFFI
  - | LiberalTypeSynonyms
  - | TypeOperators
  - | RecordWildCards
  - | RecordPuns
  - | DisambiguateRecordFields
  - | TraditionalRecordSyntax
  - | OverloadedStrings
  - | GADTs
  - | GADTSyntax
  - | MonoPatBinds
  - | RelaxedPolyRec
  - | ExtendedDefaultRules
  - | UnboxedTuples
  - | DeriveDataTypeable
  - | DeriveGeneric
  - | DefaultSignatures
  - | InstanceSigs
  - | ConstrainedClassMethods
  - | PackageImports
  - | ImpredicativeTypes
  - | NewQualifiedOperators
  - | PostfixOperators
  - | QuasiQuotes
  - | TransformListComp
  - | MonadComprehensions
  - | ViewPatterns
  - | XmlSyntax
  - | RegularPatterns
  - | TupleSections
  - | GHCForeignImportPrim
  - | NPlusKPatterns
  - | DoAndIfThenElse
  - | MultiWayIf
  - | LambdaCase
  - | RebindableSyntax
  - | ExplicitForAll
  - | DatatypeContexts
  - | MonoLocalBinds
  - | DeriveFunctor
  - | DeriveTraversable
  - | DeriveFoldable
  - | NondecreasingIndentation
  - | SafeImports
  - | Safe
  - | Trustworthy
  - | Unsafe
  - | ConstraintKinds
  - | PolyKinds
  - | DataKinds
  - | ParallelArrays
  - | RoleAnnotations
  - | OverloadedLists
  - | EmptyCase
  - | AutoDeriveTypeable
  - | NegativeLiterals
  - | BinaryLiterals
  - | NumDecimals
  - | NullaryTypeClasses
  - | ExplicitNamespaces
  - | AllowAmbiguousTypes
  - | JavaScriptFFI
  - | PatternSynonyms
  - | PartialTypeSignatures
  - | NamedWildCards
  - | DeriveAnyClass
  - | DeriveLift
  - | StaticPointers
  - | StrictData
  - | Strict
  - | ApplicativeDo
  - | DuplicateRecordFields
  - | TypeApplications
  - | TypeInType
  - | UndecidableSuperClasses
  - | MonadFailDesugaring
  - | TemplateHaskellQuotes
  - | OverloadedLabels
  - | TypeFamilyDependencies
  - | NoOverlappingInstances
  - | NoUndecidableInstances
  - | NoIncoherentInstances
  - | NoDoRec
  - | NoRecursiveDo
  - | NoParallelListComp
  - | NoMultiParamTypeClasses
  - | NoMonomorphismRestriction
  - | NoFunctionalDependencies
  - | NoRank2Types
  - | NoRankNTypes
  - | NoPolymorphicComponents
  - | NoExistentialQuantification
  - | NoScopedTypeVariables
  - | NoPatternSignatures
  - | NoImplicitParams
  - | NoFlexibleContexts
  - | NoFlexibleInstances
  - | NoEmptyDataDecls
  - | NoCPP
  - | NoKindSignatures
  - | NoBangPatterns
  - | NoTypeSynonymInstances
  - | NoTemplateHaskell
  - | NoForeignFunctionInterface
  - | NoArrows
  - | NoGenerics
  - | NoImplicitPrelude
  - | NoNamedFieldPuns
  - | NoPatternGuards
  - | NoGeneralizedNewtypeDeriving
  - | NoExtensibleRecords
  - | NoRestrictedTypeSynonyms
  - | NoHereDocuments
  - | NoMagicHash
  - | NoTypeFamilies
  - | NoStandaloneDeriving
  - | NoUnicodeSyntax
  - | NoUnliftedFFITypes
  - | NoInterruptibleFFI
  - | NoCApiFFI
  - | NoLiberalTypeSynonyms
  - | NoTypeOperators
  - | NoRecordWildCards
  - | NoRecordPuns
  - | NoDisambiguateRecordFields
  - | NoTraditionalRecordSyntax
  - | NoOverloadedStrings
  - | NoGADTs
  - | NoGADTSyntax
  - | NoMonoPatBinds
  - | NoRelaxedPolyRec
  - | NoExtendedDefaultRules
  - | NoUnboxedTuples
  - | NoDeriveDataTypeable
  - | NoDeriveGeneric
  - | NoDefaultSignatures
  - | NoInstanceSigs
  - | NoConstrainedClassMethods
  - | NoPackageImports
  - | NoImpredicativeTypes
  - | NoNewQualifiedOperators
  - | NoPostfixOperators
  - | NoQuasiQuotes
  - | NoTransformListComp
  - | NoMonadComprehensions
  - | NoViewPatterns
  - | NoXmlSyntax
  - | NoRegularPatterns
  - | NoTupleSections
  - | NoGHCForeignImportPrim
  - | NoNPlusKPatterns
  - | NoDoAndIfThenElse
  - | NoMultiWayIf
  - | NoLambdaCase
  - | NoRebindableSyntax
  - | NoExplicitForAll
  - | NoDatatypeContexts
  - | NoMonoLocalBinds
  - | NoDeriveFunctor
  - | NoDeriveTraversable
  - | NoDeriveFoldable
  - | NoNondecreasingIndentation
  - | NoSafeImports
  - | NoSafe
  - | NoTrustworthy
  - | NoUnsafe
  - | NoConstraintKinds
  - | NoPolyKinds
  - | NoDataKinds
  - | NoParallelArrays
  - | NoRoleAnnotations
  - | NoOverloadedLists
  - | NoEmptyCase
  - | NoAutoDeriveTypeable
  - | NoNegativeLiterals
  - | NoBinaryLiterals
  - | NoNumDecimals
  - | NoNullaryTypeClasses
  - | NoExplicitNamespaces
  - | NoAllowAmbiguousTypes
  - | NoJavaScriptFFI
  - | NoPatternSynonyms
  - | NoPartialTypeSignatures
  - | NoNamedWildCards
  - | NoDeriveAnyClass
  - | NoDeriveLift
  - | NoStaticPointers
  - | NoStrictData
  - | NoStrict
  - | NoApplicativeDo
  - | NoDuplicateRecordFields
  - | NoTypeApplications
  - | NoTypeInType
  - | NoUndecidableSuperClasses
  - | NoMonadFailDesugaring
  - | NoTemplateHaskellQuotes
  - | NoOverloadedLabels
  - | NoTypeFamilyDependencies
  - | UnknownExtension String
- installedModulesInScope :: MonadInterpreter m => Option m Bool
- searchPath :: MonadInterpreter m => Option m [FilePath]
- type ModuleName = String
- isModuleInterpreted :: MonadInterpreter m => ModuleName -> m Bool
- data ModuleImport = ModuleImport {
  - modName :: String
  - modQual :: ModuleQualification
  - modImp :: ImportList
  }
- data ModuleQualification
  - = NotQualified
  - | ImportAs String
  - | QualifiedAs (Maybe String)
- data ImportList
  - = NoImportList
  - | ImportList [String]
  - | HidingList [String]
- loadModules :: MonadInterpreter m => [String] -> m ()
- getLoadedModules :: MonadInterpreter m => m [ModuleName]
- setTopLevelModules :: MonadInterpreter m => [ModuleName] -> m ()
- setImports :: MonadInterpreter m => [ModuleName] -> m ()
- setImportsQ :: MonadInterpreter m => [(ModuleName, Maybe String)] -> m ()
- setImportsF :: MonadInterpreter m => [ModuleImport] -> m ()
- reset :: MonadInterpreter m => m ()
- data ModuleElem
  - = Fun Id
  - | Class Id [Id]
  - | Data Id [Id]
- type Id = String
- name :: ModuleElem -> Id
- children :: ModuleElem -> [Id]
- getModuleExports :: MonadInterpreter m => ModuleName -> m [ModuleElem]
- getModuleAnnotations :: (Data a, MonadInterpreter m) => a -> String -> m [a]
- getValAnnotations :: (Data a, MonadInterpreter m) => a -> String -> m [a]
- typeChecksWithDetails :: MonadInterpreter m => String -> m (Either [GhcError] String)
- typeOf :: MonadInterpreter m => String -> m String
- typeChecks :: MonadInterpreter m => String -> m Bool
- kindOf :: MonadInterpreter m => String -> m String
- normalizeType :: MonadInterpreter m => String -> m String
- interpret :: (MonadInterpreter m, Typeable a) => String -> a -> m a
- as :: Typeable a => a
- infer :: Typeable a => a
- eval :: MonadInterpreter m => String -> m String
- runStmt :: MonadInterpreter m => String -> m ()
- data InterpreterError
  - = UnknownError String
  - | WontCompile [GhcError]
  - | NotAllowed String
  - | GhcException String
- newtype GhcError = GhcError {
  - errMsg :: String
  }
- data MultipleInstancesNotAllowed = MultipleInstancesNotAllowed
- ghcVersion :: Int
- parens :: String -> String

# The interpreter monad transformer

class (MonadIO m, MonadMask m) => MonadInterpreter m where #

Methods

fromSession :: FromSession m a #

modifySessionRef :: ModifySessionRef m a #

runGhc :: RunGhc m a #

#### Instances

Instances details

(MonadIO m, MonadMask m, Functor m) => MonadInterpreter (InterpreterT m) # |
Instance details Defined in Hint.InterpreterT Methods fromSession :: FromSession (InterpreterT m) a # modifySessionRef :: ModifySessionRef (InterpreterT m) a # runGhc :: RunGhc (InterpreterT m) a #

data InterpreterT m a #

#### Instances

Instances details

MonadTrans InterpreterT # |
Instance details Defined in Hint.InterpreterT Methods lift :: Monad m => m a -> InterpreterT m a
MonadIO m => MonadIO (InterpreterT m) # |
Instance details Defined in Hint.InterpreterT Methods liftIO :: IO a -> InterpreterT m a
Monad m => Applicative (InterpreterT m) # |
Instance details Defined in Hint.InterpreterT Methods pure :: a -> InterpreterT m a (<*>) :: InterpreterT m (a -> b) -> InterpreterT m a -> InterpreterT m b liftA2 :: (a -> b -> c) -> InterpreterT m a -> InterpreterT m b -> InterpreterT m c (*>) :: InterpreterT m a -> InterpreterT m b -> InterpreterT m b (<*) :: InterpreterT m a -> InterpreterT m b -> InterpreterT m a
Functor m => Functor (InterpreterT m) # |
Instance details Defined in Hint.InterpreterT Methods fmap :: (a -> b) -> InterpreterT m a -> InterpreterT m b (<$) :: a -> InterpreterT m b -> InterpreterT m a
Monad m => Monad (InterpreterT m) # |
Instance details Defined in Hint.InterpreterT Methods (>>=) :: InterpreterT m a -> (a -> InterpreterT m b) -> InterpreterT m b (>>) :: InterpreterT m a -> InterpreterT m b -> InterpreterT m b return :: a -> InterpreterT m a
(MonadIO m, MonadMask m) => MonadCatch (InterpreterT m) # |
Instance details Defined in Hint.InterpreterT Methods catch :: (HasCallStack, Exception e) => InterpreterT m a -> (e -> InterpreterT m a) -> InterpreterT m a
(MonadIO m, MonadMask m) => MonadMask (InterpreterT m) # |
Instance details Defined in Hint.InterpreterT Methods mask :: HasCallStack => ((forall a. InterpreterT m a -> InterpreterT m a) -> InterpreterT m b) -> InterpreterT m b uninterruptibleMask :: HasCallStack => ((forall a. InterpreterT m a -> InterpreterT m a) -> InterpreterT m b) -> InterpreterT m b generalBracket :: HasCallStack => InterpreterT m a -> (a -> ExitCase b -> InterpreterT m c) -> (a -> InterpreterT m b) -> InterpreterT m (b, c)
MonadCatch m => MonadThrow (InterpreterT m) # |
Instance details Defined in Hint.InterpreterT Methods throwM :: (HasCallStack, Exception e) => e -> InterpreterT m a
(MonadIO m, MonadMask m, Functor m) => MonadInterpreter (InterpreterT m) # |
Instance details Defined in Hint.InterpreterT Methods fromSession :: FromSession (InterpreterT m) a # modifySessionRef :: ModifySessionRef (InterpreterT m) a # runGhc :: RunGhc (InterpreterT m) a #

type Interpreter = InterpreterT IO #

## Running the interpreter

runInterpreter :: (MonadIO m, MonadMask m) => InterpreterT m a -> m (Either InterpreterError a) #

Executes the interpreter. Returns `Left InterpreterError` in case of error.

NB. In hint-0.7.0 and earlier, the underlying ghc was accidentally overwriting certain signal handlers (SIGINT, SIGHUP, SIGTERM, SIGQUIT on Posix systems, Ctrl-C handler on Windows).

## Interpreter options

data Option m a #

Available options are:

- `languageExtensions`
- `installedModulesInScope`
- `searchPath`

data OptionVal m #

Constructors

forall a. (Option m a) := a |

get :: MonadInterpreter m => Option m a -> m a #

Retrieves the value of an option.

set :: MonadInterpreter m => [OptionVal m] -> m () #

Use this function to set or modify the value of any option. It is invoked like this:

    set [opt1 := val1, opt2 := val2,... optk := valk]

languageExtensions :: MonadInterpreter m => Option m [Extension] #

Language extensions in use by the interpreter.

Default is: `[]` (i.e. none, pure Haskell 98)

availableExtensions :: [Extension] #

List of the extensions known by the interpreter.

data Extension #

This represents language extensions beyond Haskell 98 that are supported by GHC (it was taken from Cabal's `Language.Haskell.Extension`)

Constructors

OverlappingInstances |
UndecidableInstances |
IncoherentInstances |
DoRec |
RecursiveDo |
ParallelListComp |
MultiParamTypeClasses |
MonomorphismRestriction |
FunctionalDependencies |
Rank2Types |
RankNTypes |
PolymorphicComponents |
ExistentialQuantification |
ScopedTypeVariables |
PatternSignatures |
ImplicitParams |
FlexibleContexts |
FlexibleInstances |
EmptyDataDecls |
CPP |
KindSignatures |
BangPatterns |
TypeSynonymInstances |
TemplateHaskell |
ForeignFunctionInterface |
Arrows |
Generics |
ImplicitPrelude |
NamedFieldPuns |
PatternGuards |
GeneralizedNewtypeDeriving |
ExtensibleRecords |
RestrictedTypeSynonyms |
HereDocuments |
MagicHash |
TypeFamilies |
StandaloneDeriving |
UnicodeSyntax |
UnliftedFFITypes |
InterruptibleFFI |
CApiFFI |
LiberalTypeSynonyms |
TypeOperators |
RecordWildCards |
RecordPuns |
DisambiguateRecordFields |
TraditionalRecordSyntax |
OverloadedStrings |
GADTs |
GADTSyntax |
MonoPatBinds |
RelaxedPolyRec |
ExtendedDefaultRules |
UnboxedTuples |
DeriveDataTypeable |
DeriveGeneric |
DefaultSignatures |
InstanceSigs |
ConstrainedClassMethods |
PackageImports |
ImpredicativeTypes |
NewQualifiedOperators |
PostfixOperators |
QuasiQuotes |
TransformListComp |
MonadComprehensions |
ViewPatterns |
XmlSyntax |
RegularPatterns |
TupleSections |
GHCForeignImportPrim |
NPlusKPatterns |
DoAndIfThenElse |
MultiWayIf |
LambdaCase |
RebindableSyntax |
ExplicitForAll |
DatatypeContexts |
MonoLocalBinds |
DeriveFunctor |
DeriveTraversable |
DeriveFoldable |
NondecreasingIndentation |
SafeImports |
Safe |
Trustworthy |
Unsafe |
ConstraintKinds |
PolyKinds |
DataKinds |
ParallelArrays |
RoleAnnotations |
OverloadedLists |
EmptyCase |
AutoDeriveTypeable |
NegativeLiterals |
BinaryLiterals |
NumDecimals |
NullaryTypeClasses |
ExplicitNamespaces |
AllowAmbiguousTypes |
JavaScriptFFI |
PatternSynonyms |
PartialTypeSignatures |
NamedWildCards |
DeriveAnyClass |
DeriveLift |
StaticPointers |
StrictData |
Strict |
ApplicativeDo |
DuplicateRecordFields |
TypeApplications |
TypeInType |
UndecidableSuperClasses |
MonadFailDesugaring |
TemplateHaskellQuotes |
OverloadedLabels |
TypeFamilyDependencies |
NoOverlappingInstances |
NoUndecidableInstances |
NoIncoherentInstances |
NoDoRec |
NoRecursiveDo |
NoParallelListComp |
NoMultiParamTypeClasses |
NoMonomorphismRestriction |
NoFunctionalDependencies |
NoRank2Types |
NoRankNTypes |
NoPolymorphicComponents |
NoExistentialQuantification |
NoScopedTypeVariables |
NoPatternSignatures |
NoImplicitParams |
NoFlexibleContexts |
NoFlexibleInstances |
NoEmptyDataDecls |
NoCPP |
NoKindSignatures |
NoBangPatterns |
NoTypeSynonymInstances |
NoTemplateHaskell |
NoForeignFunctionInterface |
NoArrows |
NoGenerics |
NoImplicitPrelude |
NoNamedFieldPuns |
NoPatternGuards |
NoGeneralizedNewtypeDeriving |
NoExtensibleRecords |
NoRestrictedTypeSynonyms |
NoHereDocuments |
NoMagicHash |
NoTypeFamilies |
NoStandaloneDeriving |
NoUnicodeSyntax |
NoUnliftedFFITypes |
NoInterruptibleFFI |
NoCApiFFI |
NoLiberalTypeSynonyms |
NoTypeOperators |
NoRecordWildCards |
NoRecordPuns |
NoDisambiguateRecordFields |
NoTraditionalRecordSyntax |
NoOverloadedStrings |
NoGADTs |
NoGADTSyntax |
NoMonoPatBinds |
NoRelaxedPolyRec |
NoExtendedDefaultRules |
NoUnboxedTuples |
NoDeriveDataTypeable |
NoDeriveGeneric |
NoDefaultSignatures |
NoInstanceSigs |
NoConstrainedClassMethods |
NoPackageImports |
NoImpredicativeTypes |
NoNewQualifiedOperators |
NoPostfixOperators |
NoQuasiQuotes |
NoTransformListComp |
NoMonadComprehensions |
NoViewPatterns |
NoXmlSyntax |
NoRegularPatterns |
NoTupleSections |
NoGHCForeignImportPrim |
NoNPlusKPatterns |
NoDoAndIfThenElse |
NoMultiWayIf |
NoLambdaCase |
NoRebindableSyntax |
NoExplicitForAll |
NoDatatypeContexts |
NoMonoLocalBinds |
NoDeriveFunctor |
NoDeriveTraversable |
NoDeriveFoldable |
NoNondecreasingIndentation |
NoSafeImports |
NoSafe |
NoTrustworthy |
NoUnsafe |
NoConstraintKinds |
NoPolyKinds |
NoDataKinds |
NoParallelArrays |
NoRoleAnnotations |
NoOverloadedLists |
NoEmptyCase |
NoAutoDeriveTypeable |
NoNegativeLiterals |
NoBinaryLiterals |
NoNumDecimals |
NoNullaryTypeClasses |
NoExplicitNamespaces |
NoAllowAmbiguousTypes |
NoJavaScriptFFI |
NoPatternSynonyms |
NoPartialTypeSignatures |
NoNamedWildCards |
NoDeriveAnyClass |
NoDeriveLift |
NoStaticPointers |
NoStrictData |
NoStrict |
NoApplicativeDo |
NoDuplicateRecordFields |
NoTypeApplications |
NoTypeInType |
NoUndecidableSuperClasses |
NoMonadFailDesugaring |
NoTemplateHaskellQuotes |
NoOverloadedLabels |
NoTypeFamilyDependencies |
UnknownExtension String |

#### Instances

Instances details

Read Extension # |
Instance details Defined in Hint.Extension Methods readsPrec :: Int -> ReadS Extension readList :: ReadS [Extension] readPrec :: ReadPrec Extension readListPrec :: ReadPrec [Extension]
Show Extension # |
Instance details Defined in Hint.Extension Methods showsPrec :: Int -> Extension -> ShowS show :: Extension -> String showList :: [Extension] -> ShowS
Eq Extension # |
Instance details Defined in Hint.Extension Methods (==) :: Extension -> Extension -> Bool (/=) :: Extension -> Extension -> Bool

installedModulesInScope :: MonadInterpreter m => Option m Bool #

When set to `True`, every module in every available package is implicitly imported qualified. This is very convenient for interactive evaluation, but can be a problem in sandboxed environments (e.g. `unsafePerformIO` is in scope).

Default value is `True`.

Observe that due to limitations in the GHC-API, when set to `False`, the private symbols in interpreted modules will not be in scope.

searchPath :: MonadInterpreter m => Option m [FilePath] #

The search path for source files. Observe that every time it is set, it overrides the previous search path. The default is `["."]`.

Keep in mind that by a limitation in ghc, `"."` is always in scope.

## Context handling

type ModuleName = String #

Module names are _not_ filepaths.

isModuleInterpreted :: MonadInterpreter m => ModuleName -> m Bool #

Returns True if the module was interpreted.

data ModuleImport #

Represent module import statement. See `setImportsF`

Constructors

ModuleImport |
Fields modName :: String modQual :: ModuleQualification modImp :: ImportList

#### Instances

Instances details

Show ModuleImport # |
Instance details Defined in Hint.Base Methods showsPrec :: Int -> ModuleImport -> ShowS show :: ModuleImport -> String showList :: [ModuleImport] -> ShowS

data ModuleQualification #

Constructors

NotQualified |
ImportAs String |
QualifiedAs (Maybe String) |

#### Instances

Instances details

Show ModuleQualification # |
Instance details Defined in Hint.Base Methods showsPrec :: Int -> ModuleQualification -> ShowS show :: ModuleQualification -> String showList :: [ModuleQualification] -> ShowS
Eq ModuleQualification # |
Instance details Defined in Hint.Base Methods (==) :: ModuleQualification -> ModuleQualification -> Bool (/=) :: ModuleQualification -> ModuleQualification -> Bool

data ImportList #

Constructors

NoImportList |
ImportList [String] |
HidingList [String] |

#### Instances

Instances details

Show ImportList # |
Instance details Defined in Hint.Base Methods showsPrec :: Int -> ImportList -> ShowS show :: ImportList -> String showList :: [ImportList] -> ShowS
Eq ImportList # |
Instance details Defined in Hint.Base Methods (==) :: ImportList -> ImportList -> Bool (/=) :: ImportList -> ImportList -> Bool

loadModules :: MonadInterpreter m => [String] -> m () #

Tries to load all the requested modules from their source file. Modules my be indicated by their ModuleName (e.g. "My.Module") or by the full path to its source file. Note that in order to use code from that module, you also need to call `setImports` (to use the exported types and definitions) or `setTopLevelModules` (to also use the private types and definitions).

The interpreter is `reset` both before loading the modules and in the event of an error.

IMPORTANT: Like in a ghci session, this will also load (and interpret) any dependency that is not available via an installed package. Make sure that you are not loading any module that is also being used to compile your application. In particular, you need to avoid modules that define types that will later occur in an expression that you will want to interpret.

The problem in doing this is that those types will have two incompatible representations at runtime: 1) the one in the compiled code and 2) the one in the interpreted code. When interpreting such an expression (bringing it to program-code) you will likely get a segmentation fault, since the latter representation will be used where the program assumes the former.

The rule of thumb is: never make the interpreter run on the directory with the source code of your program! If you want your interpreted code to use some type that is defined in your program, then put the defining module on a library and make your program depend on that package.

getLoadedModules :: MonadInterpreter m => m [ModuleName] #

Returns the list of modules loaded with `loadModules`.

setTopLevelModules :: MonadInterpreter m => [ModuleName] -> m () #

Sets the modules whose context is used during evaluation. All bindings of these modules are in scope, not only those exported.

Modules must be interpreted to use this function.

setImports :: MonadInterpreter m => [ModuleName] -> m () #

Sets the modules whose exports must be in context. These can be modules previously loaded with `loadModules`, or modules from packages which hint is aware of. This includes package databases specified to `unsafeRunInterpreterWithArgs` by the `-package-db=...` parameter, and packages specified by a ghc environment file created by `cabal build --write-ghc-environment-files=always`.

Warning: `setImports`, `setImportsQ`, and `setImportsF` are mutually exclusive. If you have a list of modules to be used qualified and another list unqualified, then you need to do something like

     setImportsQ ((zip unqualified $ repeat Nothing) ++ qualifieds)

setImportsQ :: MonadInterpreter m => [(ModuleName, Maybe String)] -> m () #

A variant of `setImports` where modules them may be qualified. e.g.:

`setImportsQ [(Prelude, Nothing), (Data.Map, Just M)]`.

Here, "map" will refer to Prelude.map and "M.map" to Data.Map.map.

setImportsF :: MonadInterpreter m => [ModuleImport] -> m () #

A variant of `setImportsQ` where modules may have an explicit import list. e.g.:

    setImportsF [ModuleImport Prelude NotQualified NoImportList, ModuleImport Data.Text (QualifiedAs $ Just Text) (HidingList ["pack"])]

reset :: MonadInterpreter m => m () #

All imported modules are cleared from the context, and loaded modules are unloaded. It is similar to a `:load` in GHCi, but observe that not even the Prelude will be in context after a reset.

## Module querying

data ModuleElem #

Constructors

Fun Id |
Class Id [Id] |
Data Id [Id] |

#### Instances

Instances details

Read ModuleElem # |
Instance details Defined in Hint.Reflection Methods readsPrec :: Int -> ReadS ModuleElem readList :: ReadS [ModuleElem] readPrec :: ReadPrec ModuleElem readListPrec :: ReadPrec [ModuleElem]
Show ModuleElem # |
Instance details Defined in Hint.Reflection Methods showsPrec :: Int -> ModuleElem -> ShowS show :: ModuleElem -> String showList :: [ModuleElem] -> ShowS
Eq ModuleElem # |
Instance details Defined in Hint.Reflection Methods (==) :: ModuleElem -> ModuleElem -> Bool (/=) :: ModuleElem -> ModuleElem -> Bool

type Id = String #

An Id for a class, a type constructor, a data constructor, a binding, etc

name :: ModuleElem -> Id #

children :: ModuleElem -> [Id] #

getModuleExports :: MonadInterpreter m => ModuleName -> m [ModuleElem] #

Gets an abstract representation of all the entities exported by the module. It is similar to the `:browse` command in GHCi.

## Annotations

getModuleAnnotations :: (Data a, MonadInterpreter m) => a -> String -> m [a] #

getValAnnotations :: (Data a, MonadInterpreter m) => a -> String -> m [a] #

## Type inference

typeChecksWithDetails :: MonadInterpreter m => String -> m (Either [GhcError] String) #

Similar to `typeChecks`, but gives more information, e.g. the type errors.

typeOf :: MonadInterpreter m => String -> m String #

Returns a string representation of the type of the expression.

typeChecks :: MonadInterpreter m => String -> m Bool #

Tests if the expression type checks.

NB. Be careful if `unsafeSetGhcOption "-fdefer-type-errors"` is used. Perhaps unsurprisingly, that can falsely make `typeChecks` and `typeChecksWithDetails` return `True` and `Right _` respectively.

kindOf :: MonadInterpreter m => String -> m String #

Returns a string representation of the kind of the type expression.

normalizeType :: MonadInterpreter m => String -> m String #

Returns a string representation of the normalized type expression. This is what the `:kind!` GHCi command prints after `=`.

## Evaluation

interpret :: (MonadInterpreter m, Typeable a) => String -> a -> m a #

Evaluates an expression, given a witness for its monomorphic type.

as :: Typeable a => a #

Convenience functions to be used with `interpret` to provide witnesses. Example:

-     interpret "head [True,False]" (as :: Bool)

-     interpret "head $ map show [True,False]" infer >>= flip interpret (as :: Bool)

infer :: Typeable a => a #

Convenience functions to be used with `interpret` to provide witnesses. Example:

-     interpret "head [True,False]" (as :: Bool)

-     interpret "head $ map show [True,False]" infer >>= flip interpret (as :: Bool)

eval :: MonadInterpreter m => String -> m String #

`eval expr` will evaluate `show expr`. It will succeed only if `expr` has type t and there is a `Show` instance for t.

runStmt :: MonadInterpreter m => String -> m () #

Evaluate a statement in the `IO` monad, possibly binding new names.

Example:

    runStmt "x <- return 42"
    runStmt "print x"

# Error handling

data InterpreterError #

Constructors

UnknownError String |
WontCompile [GhcError] |
NotAllowed String |
GhcException String | GhcExceptions from the underlying GHC API are caught and rethrown as this.

#### Instances

Instances details

Exception InterpreterError # |
Instance details Defined in Hint.Base Methods toException :: InterpreterError -> SomeException fromException :: SomeException -> Maybe InterpreterError displayException :: InterpreterError -> String
Show InterpreterError # |
Instance details Defined in Hint.Base Methods showsPrec :: Int -> InterpreterError -> ShowS show :: InterpreterError -> String showList :: [InterpreterError] -> ShowS

newtype GhcError #

Constructors

GhcError |
Fields errMsg :: String

#### Instances

Instances details

Show GhcError # |
Instance details Defined in Hint.Base Methods showsPrec :: Int -> GhcError -> ShowS show :: GhcError -> String showList :: [GhcError] -> ShowS

data MultipleInstancesNotAllowed #

The installed version of ghc is not thread-safe. This exception is thrown whenever you try to execute `runInterpreter` while another instance is already running.

Constructors

MultipleInstancesNotAllowed |

#### Instances

Instances details

Exception MultipleInstancesNotAllowed # |
Instance details Defined in Hint.InterpreterT Methods toException :: MultipleInstancesNotAllowed -> SomeException fromException :: SomeException -> Maybe MultipleInstancesNotAllowed displayException :: MultipleInstancesNotAllowed -> String
Show MultipleInstancesNotAllowed # |
Instance details Defined in Hint.InterpreterT Methods showsPrec :: Int -> MultipleInstancesNotAllowed -> ShowS show :: MultipleInstancesNotAllowed -> String showList :: [MultipleInstancesNotAllowed] -> ShowS

# Miscellaneous

ghcVersion :: Int #

Version of the underlying ghc api. Values are:

- `804` for GHC 8.4.x
- `806` for GHC 8.6.x
- etc...

parens :: String -> String #

Conceptually, `parens s = "(" ++ s ++ ")"`, where s is any valid haskell expression. In practice, it is harder than this. Observe that if `s` ends with a trailing comment, then `parens s` would be a malformed expression. The straightforward solution for this is to put the closing parenthesis in a different line. However, now we are messing with the layout rules and we don't know where `s` is going to be used! Solution: `parens s = "(let {foo =\n" ++ s ++ "\n ;} in foo)"` where `foo` does not occur in `s`