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.
Related
I have a large type hierarchy in Haskell.
Counting family instances, which (can) have separate class membership after all, there are hundreds of data types.
Since the top-most type needs to implement built-in classes like Generic,Eq,Ord,Show, every single type in the hierarchy has to as well for a meaningful implementation overall. So my specification contains hundreds of times deriving (Generic,Eq,Ord,Show), which I would like to avoid cluttering the files.
A solution involving a single typeclass to attach everywhere like deriving GEOS with a single automatic derivation from that to the usual set in a centralized place would already help a lot with readability.
Another question asking for similar conciseness in constraints is solved by using constraint synonyms (so my GEOS would be not just linked to but explicitly made up of exactly the classes I want), which however apparently are currently prevented from being instantiated.
(A side question of mine would be why that is so. It seems to me like the reason #simonpj gives about the renamer not knowing what the type checker knows the synonym really to be would only apply to explicitly written out instance implementations.)
Maybe GHC.Generic itself (and something like generic-deriving) could help here?
You could of course use Template Haskell, to generate the deriving-clauses as -XStandaloneDeriving.
{-# LANGUAGE QuasiQuotes #-}
module GEOSDerive where
import Language.Haskell.TH
import Control.Monad
import GHC.Generics
deriveGEOS :: Q Type -> DecsQ
deriveGEOS t = do
t' <- t
forM [ [t|Generic|], [t|Eq|], [t|Ord|], [t|Show|] ] $ \c -> do
c' <- c
return $ StandaloneDerivD Nothing [] (AppT c' t')
Then,
{-# LANGUAGE TemplateHaskell, StandaloneDeriving, QuasiQuotes, DeriveGeneric #-}
import GEOSDerive
data Foo = Foo
deriveGEOS [t|Foo|]
But, I find it somewhat dubious that you need so many types in the first place, or rather that you have so many types but each of them has so little code associated with it that you're bothered about mentioning those four classes for each of them. It's not like there's anything to be concerned about regarding refactoring or so with those, so I'd rather recommend simply keeping with deriving (Generic, Eq, Ord, Show) for each of them.
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.
Following this tutorial, I have the following code:
{-# LANGUAGE DataKinds, TypeFamilies #-}
data Nat = Z | S Nat
type family Plus (n :: Nat) (m :: Nat) :: Nat
type instance Plus Z m = m
type instance Plus (S n) m = S (Plus n m)
So far so good. I know that DataKinds does auto promotion of types to kinds, and TypeFamilies enable type-level functions.
Then I add:
type family Mul (m :: Nat) (n :: Nat) :: Nat
type instance Mul Z m = Z
type instance Mul (S n) m = Plus m (Mul n m)
Compiling gives me:
Nested type family application
in the type family application: Plus m (Mul n m)
(Use UndecidableInstances to permit this)
In the type instance declaration for ‘Mul’
The name of this extension is scary. Some people say to avoid it, and explanations of this extension I've tried reading do not make sense to me.
Looking for a bit of help in understanding the error, why it is showing up in this example, what is the meaning of undecidable in this context and in what instances this extension is as scary as it sounds?
It's not really scary. It disables the (rather weak) GHC checks that try to ascertain that type family and instance definitions terminate. So, its worst case behavior is non-terminating type checking. However, most often we get error messages instead of actual looping, because loops often exceed stack limits in the type checker. We don't get unsafety, incoherence or any other property that may adversely affect program robustness or inference.
"Undecidable" is probably a stronger expression than warranted, since it only denotes that GHC can't decide whether a definition is terminating. In many cases it's GHC that's too weak for the job, and other compilers for dependent languages would be able to check termination without problem. With GHC, UndecidableInstances is often required for obviously terminating definitions too, in which cases its usage is quite justified.
UndecidableInstance is ok to use. Granted, you should always consider a moment whether something is really needed, or it would be more idiomatic to choose another path.
Luke makes the point that UndecidableInstances should not be used to implement superclassing. Well, that's true, but it doesn't really have much to do with undecidable instances – superclassing is just always a hack and pretty much backwards to the way abstractions should be designed.
It is IME not true, at least not anymore, that superclassing is the most common use of UndecidableInstances. There are plenty of things you can do with this extension enabled but not without. Most certainly, it can't be possible to impose a halting-proof condition if you actually want to do Turing-complete dependent typing at compile-time, which is basically what all the DataKinds fuzz is heading to.
So, don't worry too much; indeed you probably won't get around UndecidableInstances. As said by András Kovács, this extension is perfectly safe WRT correctness, the worst that can happen is a loop / error.
If that's too scary for your tastes, use a language that's designed up front as dependently-typed and total, i.e. Agda.
I can think of three ways to define a geometric point as an algebraic data type in Haskell. I want to define it as an algebraic data type for better documentation.
As a tuple type:
data Point a = Point a a
As a tuple:
data Point a= Point (a,a)
As a record:
data Point a = Point { pointx :: a, pointy :: a}
Which is better design/style and why?
I think this depends mostly on your use-case at hand.
Though I'd never use data Point = Point (a, a), because this introduces one layer of indirection, which bloats the data structure - by two machine words - one for the Point and one for the pointer pointing to the tuple inside it.
Better use type Point a = (a,a) which is just an alias or newtype Point a = Point (a,a) which gets optimized away at compile time, so you have the benefits in this case.
The most flexible (for some definitions of flexible) is the last approach, though I'd call the records pr1 and pr2 for 'projection to the first/second component'. This approach also lends itself nicely to using lenses.
As #nikitavolkov said - it is a good idea to have strict data fields for performance reasons, but as I like records I'd ultimately go with
{-# LANGUAGE TemplateHaskell -#}
{-# LANGUAGE DeriveFoldable -#}
{-# LANGUAGE DeriveFunctor -#}
{-# LANGUAGE DeriveTraversable -#}
{-# LANGUAGE RecordWildCards #-}
import Control.Lens
data Point a = Point { _pr1 :: !a
, _pr2 :: !a
} deriving (..)
$(makeLenses ''Point)
which gets you the benefit of using norm Point{..} = sqrt (_pr1^2 + _pr2^2) with RecordWildCards and all the niceties of lenses.
Update (2017-09-03):
Just recently I found the strict package, which provides strict datatytpes as well as strict IO actions. One thing that stuck out to me was the following from Data.Strict.Maybe
Note that strict Maybe is not a monad since return ⊥ >>= f = ⊥ which is not necessarily the same as f ⊥.
Which I think is applicable to strict pairs as well - so keep that in mind when defining and/or using strict data types.
Records are a controversial subject in Haskell. There is a consensus in the community that the existing implementation is suboptimal due to many reasons and things are being done to fix that.
Now, since the existing records implementation is suboptimal, many Haskellers tend to never use them. I'm one of those.
I would recommend going with the following:
{-# LANGUAGE DeriveFoldable, DeriveFunctor, DeriveTraversable #-}
data Point a =
Point !a !a
deriving (Functor, Foldable, Traversable)
This will give you free instances of some standard classes and strict data-structures are a recommended default.
According to me,tougher one is tuple,because it is difficult to create any change in the tuples. The best one is last one.
Can someone point me at a good set of examples for defining Typeable or Typeable1 instances for GADTs in Haskell.
Or, can someone just show my how to define Typeable (manually) for the following GADT.
data V a where
Unit :: V ()
Pair :: V a -> V b -> V (a, b)
L :: V a -> V (Either a b)
R :: V b -> V (Either a b)
Fresh :: Int -> V a
Alternately a pointer to the paper that introduced the idea would also be helpful.
Looks like the website is gone now, but the wayback machine still has the site that links to all the original papers: http://web.archive.org/web/20080622204226/http://www.cs.vu.nl/boilerplate/
In any case, Typeable is almost completely mechanical. You can just derive it, even for GADTs, via the DeriveDataTypeable extension. At least when the kind is * -> *, as in your example.
I can also give an example of manually providing a Typeable1 instance, but it will be deprecated in the next version of GHC. The interface used for creating instances by hand is changing.
{-# NOINLINE vTyCon #-}
vTyCon :: TyCon
vTyCon = mkTyCon "ModuleName.V"
instance Typeable1 V where
typeOf1 _ = mkTyConApp vTyCon []
The NOINLINE pragma is actually important, since mkTyCon does unsafe stuff under the hood. This is why it's best to just let GHC derive the instance manually, if possible.
My understanding is the part that will be changing in future versions of GHC is that you should use a different function, mkTyCon3, which takes the package name, module name, and type name as separate arguments. That's a clear improvement, even if makes supporting multiple version of GHC tougher. See: Changes to Data.Typeable.
All of the above is really old.
From the GHC docs:
Also since GHC 7.8.1, handwritten (ie. not derived) instances of Typeable are forbidden, and will result in an error.
You should never need, or even be allowed, to write a Typeable instance by hand with any modern version of GHC. In fact, you don't even need to tell GHC to derive them - it will do that automatically.