Haskell error when using the isNothing function in Maybe - haskell

I am trying to use isNothing in my code in Haskell, and it is giving me the error
<interactive>:97:23: error:
• Variable not in scope: isNothing :: Maybe t -> Bool
• Perhaps you meant data constructor ‘Nothing’ (imported from Prelude)
The code line I have is as follows -
maybeMap f value = if isNothing (value) then value else Just (f (check value))
this works fine if I replace isNothing value with value == Nothing, so I am confused why the previous is not working.

First thing's first, the key phrase in the error message is:
Variable not in scope: isNothing
Which means that the compiler just isn't aware of anything named isNothing.
That immediately tells you that the code around your your use of isNothing doesn't matter. It's not a problem with types, or anything to do with the actual isNothing function you're trying to call, and there's no way you can change the code around isNothing to get this to work.
Variable not in scope almost always means one of three things:
You haven't imported the name you're trying to use
You have accidentally misspelled the name you're trying to use
You intended to define something with that name, but haven't done so yet
Changing any of the code surrounding your use of isNothing isn't going to change any of those 3 problems no matter which it is. Even looking at that code isn't going to tell you anything relevant; just closely look at the spelling of the name in the error message to confirm you haven't just made a typo, and if not you know you need to look elsewhere.
In this case it's #1. There are a bunch of useful functions that are in the Haskell Prelude which are automatically imported for you, so you're probably used to just using functions without importing them, but the "normal" case is that to use anything that's already defined you have to import it. isNothing isn't in the Prelude, so that means to use it you have to find out which module it is in and add an import declaration to make it available. (If that module is in a package that isn't already installed, you will also have to obtain the package; that's a question I'm not going to address here)
isNothing comes from the Data.Maybe module (in the base package, which is always installed as part of installing GHC, so no worries there). So you need to use:
import Data.Maybe
If you're working in a file you need to add that to the top of the file (just after the module header, but before you define any names yourself; all imports must come before any of your own code). If you're using the interpreter you can just enter the import as a command.
That will bring all of the names defined in Data.Maybe into scope. If you want more control, you can explicitly import only some of the names, like this:
import Data.Maybe ( isNothing, isJust, listToMaybe )

The function isNothing is not part of the standard prelude. Rather, it's distributed as part of the Data.Maybe module. To use isNothing, you'll need to explicitly import that module:
import Data.Maybe

Related

How can I get GHC to emit a warning for a given function?

Suppose I've decided that everywhere in a given code base (package) I want to use a custom getCurrentTimeMicroseconds rather than getCurrentTime. Is there a way for me to get GHC to emit warnings me about uses of getCurrentTime, only in that code base? (Not for anything upstream or downstream.)
Bonus question, suppose I want to selectively allow usages with an explicit annotation at the use site (preferably not module-wide). Is this also possible?
This is what types are for. The type you use for times should reflect the constraints you want to place on the values it represents.
For example, you could wrap UTCTime like so:
newtype UTCTimeMicroseconds = UTCTimeMicroseconds { picos :: UTCTime }
microsecondsFromPicos :: UTCTime -> UTCTimeMicroseconds
microsecondsFromPicos = ...
getCurrentTimeMilliseconds :: IO UTCTimeMicroseconds
getCurrentTimeMilliseconds = microsecondsFromPicos <$> getCurrentTime
And use the new type everywhere in your package that you need times to have this property.
If you want to be strict about it, don't export the UTCTimeMicroseconds constructor, so the only way to get one of these values is to use microsecondsFromPicos, which enforces your requirement.
That makes any misuse an error, not a warning, but in most cases that's what you want anyway.
When you do want to use UTCTime with the full resolution, or just don't care, you can just use that type as usual. It'll be easy to find the places in your code base where that happens, because they'll be the only places where UTCTime is used.
I can't think of a way to do this right now, but I think the closest you can get is something like:
create a new package my-time that depends on time
re-export your shim functions annotated with warnings, like
import qualified Data.Time as Time
{-# WARNING getCurrentTime "you should prefer getCurrentTimeMicroseconds" #-}
getCurrentTime = Time.getCurrentTime
depend on my-time in your packages
obviously this doesn't give you a way to enforce not importing Data.Time.getCurrentTime, and is even less satisfying when the code you want to shim is in Prelude or base.

In TemplateHaskell, how do I figure out that an imported module has been renamed?

I am writing a bit of TemplateHaskell for stringing together QuickCheck style specifications. I require every module containing properties to export a symbol called ''axiom_set''. Then, my checkAxioms function finds all the ''axiom_set'' symbols from modules imported where I call checkAxioms.
checkAxioms :: DecsQ
checkAxioms = do
ModuleInfo ms <- reifyModule =<< thisModule
forM_ ms $ \mi#(Module _ m) -> do
runIO . print =<< lookupValueName (modString m ++ ".axiom_set")
The above code should find all the imported "axiom_set" symbols. However, if Module.Axioms defines axiom_set but that I imported as follows
import Module.Axioms as MA
my code can't find MA.axiom_set. Any advice?
I don't think there's a way to do that. This seems to be a limitation of TemplateHaskell.
It kinda makes sense to have only fully qualified names in ModuleInfos list of imported modules, but the fact that we can't use those fully qualified names in lookupValueName is bad. I think we need a variant of lookupValueName or lookupName that takes a Module as argument.
I suggest openning an issue at GHC issue tracker: https://ghc.haskell.org/trac/ghc/newticket We have ongoing work to improve TH in the next major release. Part of the work is about improving the package documentation, exported functions etc. This can be one of the improvements.

Obtaining TH.Name for '[] without -XTemplateHaskell

Is there a way to obtain (import from base modules or write expression) a value of type Language.Haskell.TH.Name that represents '[] without enabling -XTemplateHaskell?
A good reason to do so is that tools like hlint do not play well with TH and being able to avoid it therefore has a benefit. Then I could put a definition
nilName :: Name
nilName = '[]
in a separate file and import it, but this only makes sense if there is no standard name by which it can be imported or called. Furthermore, nilName cannot be used in pattern matches. Is there such a thing?
import Language.Haskell.TH.Syntax
nilName = mkNameG DataName "ghc-prim" "GHC.Types" "[]"
is an equivalent definition of nilName, even though it is ugly. It can be expanded to a form that admits to pattern matching yielding to
nilName = Name (OccName "[]") (NameG DataName (PkgName "ghc-prim") (ModName "GHC.Types"))
which is not nicer nor robust. It seems that the best route forward is a combination of the above nilName defined in a separate TH-enabled module together with (== nilName) instead of pattern matching.

Why do these corner cases in Haskell's import-as work and what do they do?

I've come across some modules that contain particularly strange imports.
First of all, I have seen a module A that imports an other module as himself. For example:
-- module A.hs
module A where
import B as A -- ???
f = id
What does this do? Why is the above permitted at all?
However what most troubles me is that the code is actually of this kind:
module A where
import B as A -- Okay, assume this works...
import C as A -- ??? A is already defined!
f = id
Why can more then one module be imported with the same name? What does this achieve?
I thought that these kind of imports weren't permitted and also A Gentle Introduction to Haskell states that:
it is illegal to import two different entities having the same name
into the same scope.
However these imports work fine. Yet an other strange thing that bugs me is exporting the module itself:
module A (module A) where
To summarize, given the following MWE:
-- A.hs
module A (module A) where
import B as A
import C as A
f = id
-- B.hs
module B where
g = id
-- C.hs
module C where
h = id
Are the imports following the standards or is this some bug of GHC? It doesn't look like a bug, but I can't find any reference that explains all these corner cases.
What's the exact result achieved? I mean: which names are imported and/or exported from A?
Name qualifiers are not the same thing as module names. A name qualifier is just a collective scope, you can make it refer to any number of modules. Normally you won't add more than one, but in one case you almost always add plenty of modules: in the unqualified scope. import Data.List might be read as something like import qualified Data.List as "": it arranges that, say, sortBy will be found when referring to it with an "empty qualifier", i.e. with none. But we could "rename" that scope:
module Main where
import qualified Prelude as P
import qualified Data.List as P
import qualified Data.Ord as P
main :: P.IO ()
main = do -- `do` is syntax, not a name!
P.print P.. P.map P.snd P.$ P.sortBy (P.comparing P.fst)
[(4,'o'),(6,' '),(0,'H'),(1,'e'),(3,'l'),(9,'r'),(7,'W'),(10,'l'),(8,'o'),(2,'l'),(5,','),(11,'d'),(12,'!')]
The only qualifiers that are fixed are the ones specific to the module in your file itself: that's always both in unqualified scope, and in the scope automatically named after the module. And for definitions, you must use the unqualified form.
For module A (module A), that seems pretty much bogus. I don't think module exports are really well thought-through. They only work properly when you refer to an actual module, not just a name qualifier, i.e.
module PowerPrelude (module A)
import qualified Prelude as A
import qualified Data.List as A
import qualified Data.Ord as A
will not work. Which makes you wonder why it's allowed to declare such an export at all. Might indeed be a bug here.

How to get the literal value of a TemplateHaskell named variable

If I have a Name in TemplateHaskell and want to find out the value of the variable that it names, provided that the variable is declared as a literal, can this be done?
var = "foo"
-- Can `contentsOf` be defined?
$((contentsOf . mkName $ "var") >>= guard . (== "foo"))
In theory, yes. In practice, no.
Finding out stuff about existing names is done using reify :: Name -> Q Info, and for a definition like that you would get back a VarI value, which includes a Maybe Dec field. This would seem to suggest that you might in some cases be able to get the syntax tree for the declaration of the variable, which would allow you to extract the literal, however current versions of GHC always returns Nothing in this field, so you're out of luck for a pure TH solution.
However, TH does allow arbitrary IO actions to be run, so you could potentially work around this by loading and parsing the module yourself using something like haskell-src-exts, however I suspect that would be more trouble than it's worth.

Resources