Apply Haskell Language Pragma to Block of Code (rather than entire module) - haskell

Is it possible in Haskell to apply a language pragma to a block of code, rather than the entire file itself?
For example, I enable the -fwarn-monomorphism-restriction flag, but I have a couple of files where I'd really like to disable this flag, so I use {-# LANGUAGE NoMonomorphismRestriction #-} at the top of the file.
However, instead of applying this pragma to the entire module, I'd like to apply it only to the block of code where I don't think this warning is helpful. Only solution I can think of right now is move this block of code to its own file and then import it

In general there is no way to do this, no.
For this particular pragma, you can disable the monomorphism restriction for a single declaration by giving it a type signature. Although I strongly recommend giving a full signature, there may be some situation where that is undesirable for some reason; in such a case even a signature full of holes is sufficient, e.g.
{-# LANGUAGE PartialTypeSignatures #-}
x :: _ => _
x = (+)
will be inferred to have type Num a => a -> a -> a instead of Integer -> Integer -> Integer.

Related

Understanding the implementation of Data.Word

I'm trying to use Data.Word but I don't even understand its source code. Here are some precise questions I have, but if you have a better resource for using Word or similar libraries, that might be helpful too.
For reference, let's look at the implementation of Word8 (source)
data {-# CTYPE "HsWord8" #-} Word8 = W8# Word#
What are the #s? As far as I can tell it's not part of the name or a regular function.
What is the declaration before Word8 ({-# CTYPE "HsWord8" #-})? I have seen those as language declarations at the begining of files but never in a definition.
As far as I can tell W8 or W8# (I don't even know how to parse it) is not defined anywhere else on the file or imported. Is it being implicitly defined here or em I missing something?
Similarly Word# is used in all definitions of Word, but I don't see it defined anywhere... where is it coming from and how can I see its definition?
What are the #s?
They are only marginally more special than the Ws, os, rs, and ds -- just part of the name. Standard Haskell doesn't allow this in a name, but it's just a syntactic extension (named MagicHash) -- nothing deep happening here. As a convention, GHC internals use # suffixes on types to indicate they are unboxed, and # suffixes on constructors to indicate they box up unboxed types, but these are just conventions, and not enforced by the compiler or anything like that.
What is the declaration before Word8 ({-# CTYPE "HsWord8" #-})?
CTYPE declares that, when using the foreign function interface to marshall this type to C, the appropriate C type to marshall it to is HsWord8 -- a type defined in the GHC runtime's C headers.
As far as I can tell W8 or W8# (I don't even know how to parse it) is not defined anywhere else on the file or imported. Is it being implicitly defined here?
Well, it is being defined there, but I wouldn't call it implicit; it's quite explicit! Consider this typical Haskell data declaration:
data Foo = Bar Field1 Field2
It defines two new names: Foo, a new type at the type level, and Bar, a new function at the computation level which takes values of type Field1 and Field2 and constructs a value of type Foo. Similarly,
data Word8 = W8# Word#
defines a new type Word8 and a new constructor function W8# :: Word# -> Word8.
Similarly Word# is used in all definitions of Word, but I don't see it defined anywhere... where is it coming from and how can I see it's definition.
Word# may be imported from GHC.Exts. You can discover this yourself via Hoogle. It is a compiler primitive, so while it is possible to look at its source, the thing you would be looking at would be metacode, not code: it would not be valid Haskell code declaring the type with a standard data declaration and listing constructors, but rather some combination of C code and Haskell code describing how to lay out bits in memory, emit assembly instructions for modifying it, and interact with the garbage collector.
Well, #DanielWagner covered most of this, but I was just about done writing this up, so maybe it'll provide some additional detail... I was originally confused about the nature of the "definitions" in GHC.Prim, so I've updated my answer with a correction.
You should be able to effectively use the Data.Word types without understanding the source code in GHC.Word.
Data.Word just provides a family of unsigned integral types of fixed bitsize (Word8, Word16, Word32, and Word64) plus a Word type of "default size" (same size as Int, so 64 bits on 64-bit architectures). Because these types all have Num and Integral instances, the usual operations on integers are available, and overflow is handled the usual way. If you want to use them as bit fields, then the facilities in Data.Bits will be helpful.
In particular, I don't see anything in the GHC.Word source that could possibly help you write "normal" code using these types.
That being said, the # character is not normally allowed in identifiers, but it can be permitted (only as a final character, so W# is okay but not bad#Identifier) by enabling the MagicHash extension. There is nothing special about such identifiers EXCEPT that specific identifiers are treated "magically" by the GHC compiler, and by convention these magic identifiers, plus some other identifiers that aren't actually "magic" but are intended for internal use only, use a final # character to mark them as special so they don't accidentally get used by someone who is trying to write "normal" Haskell code.
To illustrate, in the definition:
data {-# CTYPE "HsWord8" #-} Word8 = W8# Word#
the identifier W8# is not magic. It's just a regular constructor that's intended only for internal, or at least advanced, use. On the other hand, Word# is magic. It's internally defined by GHC as an "unboxed" unsigned integer (64 bits on 64-bit architectures) where "unboxed" here means that it's stored directly in memory in an 8-byte field without an extra field for its constructor.
You can find a nonsensical "definition", of sorts, in the source code for GHC.Prim:
data Word#
In normal Haskell code, this would define a data type Word# with no constructor. Such a data type would be "uninhabited", meaning it has no possible values. However, this definition isn't actually used. This GHC.Prim source code is automatically generated for the benefit of the Haddock documentation utility. Instead, GHC.Prim is a sort of virtual module, and its "real" implementation is build into the GHC compiler.
How do you know which identifiers ending in # are magic and which aren't? Well, you don't know just by looking at the names. I believe you can reliably tell by checking in GHCi if they are defined in the virtual GHC.Prim module:
> :set -XMagicHash
> import GHC.Prim
> :i Word#
data Word# :: TYPE 'GHC.Types.WordRep -- Defined in ‘GHC.Prim’
Anything defined in GHC.Prim is magic, and anything else isn't. In the generated GHC.Prim source, these magic identifiers will show up with nonsense definitions like:
data Foo#
or:
bar# = bar#
Constructs of the form {-# WHATEVER #-} are compiler pragmas. They provide special instructions to the compiler that relate to the source file as a whole or, usually, to "nearby" Haskell code. Some pragmas are placed at the top of the source file to enable language extensions or set compiler flags:
{-# LANGUAGE FlexibleInstances #-}
{-# OPTIONS_GHC -Wall #-}
Others are interleaved with Haskell code to influence the compiler's optimizations:
double :: Int -> Int
{-# NOINLINE double #-}
double x = x + x
or to specify special memory layout or handling of data structures:
data MyStructure = MyS {-# UNPACK #-} !Bool {-# UNPACK #-} !Int
These pragmas are documented in the GHC manual. The CTYPE pragma is a rather obscure pragma that relates to how the Word type will be interpreted when used with the foreign function interface and the capi calling convention. If you aren't planning to call C functions from a Haskell program using the capi calling convention, you can ignore it.

Haskell: ScopedTypeVariables needed in pattern matching type annotations

Why does this code require the ScopedTypeVariables extension?
{-# LANGUAGE ScopedTypeVariables #-}
char = case Just '3' of
Just (x :: Char) -> x
Nothing -> '?'
When I read the documentation on ScopedTypeVariables, it seems to mean unifying type variables in the function body with the parent function signature. This code snippet isn't unifying any type variables though!
Also what is the effect of loading ScopedTypeVariables without also loading ExplicitForAll? All the other usecases of ScopedTypeVariables seem to require ExplicitForAll to actually work. But in the above snippet, there's no ExplicitForAll.
ScopedTypeVariables enables ExplicitForAll automatically For the sake of your sanity I would suggest always using ScopedTypeVariables when using any other type system extensions (except possibly the ones dealing only with classes/instances/contexts) and never using ExplicitForAll directly.
The reason ScopedTypeVariables is required for pattern variable signatures is just that such signatures are part of the extension. Among other uses, they give you a way to bring a type variable into scope. For example:
f (Just (x::a)) = bob
where
bob::[a]
bob = [x]
I do not know why the pattern signatures are part of ScopedTypeVariables, per se; most likely they were created for this purpose, and all the code was written in one go. Teasing them apart to make orthogonal extensions was almost certainly considered more trouble than it was worth.
Edit
Actually, there's a pretty good reason. With the exception of pattern bindings, a type variable in a pattern signature is generalized, bringing that variable into scope. So in the above example, you don't need to know if there is an a in the outer type environment. If you could enable pattern signatures without scoped type variables, then the variable could be generalized or not depending on whether scoped type variables were turned on or not. The same sort of confusion happens for ExplicitForAll without ScopedTypeVariables, which is why I'd like to kill that extension and make ScopedTypeVariables the default, or at least turn it on automatically with the extensions that currently enable ExplicitForAll.

Purpose of {-# #-} in Haskell

I am going through Haskell code to see how I could write similar stream fusion functions and I noticed a funny syntax construct, {-# ... #-}, that I've not come across; so I would like to know what it is and how I can find out how it works:
-- | /O(n)/ Drop elements that do not satisfy the predicate
filter :: Vector v a => (a -> Bool) -> v a -> v a
{-# INLINE filter #-}
filter f = unstream . inplace (MStream.filter f) . stream
More specifically, what does particular line do?
{-# INLINE filter #-}
GHC has a "pragma" system which allows you to specify extra-linguistic information to GHC. In particular, they look like
{-# <NAME> <ARGS...> #-}
The most common you will see are the language extension pragmas which must go at the top of a file and affect the language extensions in effect for the remainder of the file.
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Example where
Normally it ought to be that ignoring a pragma does not affect the meaning of the program. This is broadly true for pragmas like INLINE as they are merely hints to the compiler that this function's body should be inlined wherever it is called in order to open up new optimization opportunities. Haskell semantics gives us guarantees about when such inlining transformations do not change the meaning of the program, thus the choice the compiler makes about whether or not to inline has no effect on the meaning of the program (so long as it doesn't violate the assumptions of those guarantees).
The LANGUAGE pragmas are a bit different in that they specify exactly what language is being written in for the rest of the file. For instance, we typically assume the base language is Haskell98 or Haskell2010 and the LANGUAGE pragmas add extensions such that the language of the file with the headed exemplified earlier is
Haskell2010 + RankNTypes + FlexibleInstances + ScopedTypeVariables
but beyond hinting to the compiler which language is being written these pragma have no further meaning.
The full set of allowable pragma depend upon the compiler being used. GHC's pragmas are listed here (note that this link is for version 7.6.3 while the link in the comments is for 7.0.3). Use of pragmas other than LANGUAGE may be sketchy and platform specific, so learn their use and meaning carefully.
For instance, there's a big debate about whether or not library authors should use INLINE as it tends to suggest a lack of faith in GHC's own inlining heuristics and thus that we should spend more effort tightening those up rather than littering code with manual INLINEs. But that said, INLINE and INLINABLE can have profound impact on tight inner loops if used judiciously.
It's a pragma. It's basically something not expressible in the language standard itself, but still saying something relevant to the compiler.
Some of these pragmas are essentially optional, just e.g. improve performance, hence the comment-like look. In your example, INLINE means the compiler should try hard to not just link to the function in question, but actually "hard-code" it anywhere it's called. This does not in principle change program semantics, but can have quite an impact on performance and memory usage (in particular if combined with extra stream fusion etc. techniques).

Downsides to ScopedTypeVariables

What are the downsides to ScopedTypeVariables, if there are any? Why isn't it on by default? Does it lead to worse inference? Are there edge cases where it fails? Is it significantly harder to implement in GHC?
It's also because it changes the semantics of a program (combined with other extensions). Consider
{-# LANGUAGE RankNTypes #-}
foo :: forall a . (a -> a) -> (a -> a)
foo = bar
where
bar :: a -> a
bar = id
It compiles fine, but with ScopedTypeVariables it even fails to compile.
It isn't on by default for the same reason every other extension isn't on by default - it isn't part of the Haskell standard.
As augustss said - this requires more logic in the type checker but I don't think anyone considers it burdensome.

How to write an instance for all types in another type class?

I have to define a type class Truthy which contains a method true converting an instance of the type class to a Bool value.
My type class declaration:
class Truthy a where
true :: a -> Bool
Next, I have to define instances of this class for various types, including list and numeric types. I have done it for lists and Ints, but is there a way to do it for all numeric types at once?
Based on my Int declaration:
instance Truthy Int where
true = (/=) 0
I have tried adding type class constraint, but it does not work:
instance (Num a) => (Truthy a) where
true = (/=) 0::a
If there is a way to do this similar to what I had in mind, or should I just define it for each numeric type separately?
This might not help for homework, but you actually can write a declaration like that. You just have to enable -XFlexibleInstances to do so. At least in GHC, you can do this by putting a pragma at the top of your file:
{-# LANGUAGE FlexibleInstances #-}
If you look closely at the error message you got, it said something like "Use -XFlexibleInstances if you want to disable this.".
In this particular case, you would also need to enable UndecidableInstances and OverlappingInstances:
{-# LANGUAGE FlexibleInstances, UndecidableInstances, OverlappingInstances #-}
You need FlexibleInstances because standard Haskell does not allow instances in any form where the type variable appears more than once in the head. This is completely fine--I it is one of the most common extensions used (as per this question).
You need UndecidableInstances because your instance declaration could potentially cause the type checker to loop forever. I think using UndecidableInstances prevents this by limiting how deeply it will check when trying to reduce the instance. This is usually--including in this case--fine, but could theoretically make whether a particular program passes the type checks implementation dependent. Still, it should work in your case.
As hammar pointed out, you need to enable OverlappingInstances because the "context" of the instance is ignored when checking whether they overlap. The context is the Num a bit in this case. So the instances--for checking if it overlaps--is read as instance Truthy a... and overlaps with everything. With OverlappingInstances enabled, you just need to have one instance that is the most specific for this to work.

Resources