1
1
mirror of https://github.com/sdiehl/wiwinwlh.git synced 2024-09-11 12:05:25 +03:00

Write more

This commit is contained in:
sdiehl 2020-02-14 15:43:43 +00:00
parent 88e9fa0b21
commit 880ce2e9cf

View File

@ -4475,8 +4475,6 @@ ex3 = evalState (1 :: Double, 0 :: Double) (runThrow example2)
<hr/>
TODO START HERE
Language Extensions
===================
@ -4621,8 +4619,8 @@ with the low-level byte representations of data structures.
The Dangerous
-------------
GHC's typechecker sometimes just casually tells us to enable language extensions
when it can't solve certain problems. Unless you know what you're doing, these
GHC's typechecker sometimes casually tells us to enable language extensions when
it can't solve certain problems. Unless you know what you're doing, these
extensions almost always indicate a design flaw and shouldn't be turned on to
remedy the error at hand, as much as GHC might suggest otherwise!
@ -4667,7 +4665,7 @@ The problem is that GHC has inferred an overly specific type:
bar :: Integer -> Integer
```
We can prevent GHC from specializing the type with this extension, i.e.
We can prevent GHC from specializing the type with this extension:
```haskell
{-# LANGUAGE NoMonomorphismRestriction #-}
@ -4691,9 +4689,8 @@ In the absence of explicit type signatures, Haskell normally resolves ambiguous
literals using several defaulting rules. When an ambiguous literal is
typechecked, if at least one of its typeclass constraints is numeric and all of
its classes are standard library classes, the module's default list is
consulted, and the first type from the list that will satisfy the context of
the type variable is instantiated. So for instance, given the following default
rules
consulted, and the first type from the list that will satisfy the context of the
type variable is instantiated. For instance, given the following default rules
```haskell
default (C1 a,...,Cn a)
@ -4704,18 +4701,18 @@ ambiguous type variable to.
1. The type variable ``a`` appears in no other constraints
1. All the classes ``Ci`` are standard.
1. At least one of the classes ``Ci`` is numeric.
1. At least one of the classes ``Ci`` is numerical.
The default ``default`` is ``(Integer, Double)``
The standard ``default`` definition is implicitly defined as ``(Integer, Double)``
This is normally fine, but sometimes we'd like more granular control over
defaulting. The ``-XExtendedDefaultRules`` loosens the restriction that we're
constrained with working on Numerical typeclasses and the constraint that we can
only work with standard library classes. If we'd like to have our string
literals (using ``-XOverloadedStrings``) automatically default to the more
efficient ``Text`` implementation instead of ``String`` we can twiddle the flag
and GHC will perform the right substitution without the need for an explicit
annotation on every string literal.
only work with standard library classes. For example, if we'd like to have our
string literals (using ``-XOverloadedStrings``) automatically default to the
more efficient ``Text`` implementation instead of ``String`` we can twiddle the
flag and GHC will perform the right substitution without the need for an
explicit annotation on every string literal.
```haskell
{-# LANGUAGE OverloadedStrings #-}
@ -4785,10 +4782,11 @@ See:
RecursiveDo
-----------
Recursive do notation allows use of self-reference expressions on both sides of
a monadic bind. For instance the following uses lazy evaluation to generate an
infinite list. This is sometimes used to instantiate a cyclic datatype inside a
monadic context that needs to hold a reference to itself.
Recursive do notation allows for the use of self-reference expressions on both
sides of a monadic bind. For instance the following example uses lazy evaluation
to generate an infinite list. This is sometimes used to instantiate a cyclic
datatype inside a monadic context where the datatype needs to hold a reference
to itself.
```haskell
{-# LANGUAGE RecursiveDo #-}
@ -4853,7 +4851,7 @@ Pattern guards are an extension to the pattern matching syntax. Given a ``<-``
pattern qualifier, the right hand side is evaluated and matched against the
pattern on the left. If the match fails then the whole guard fails and the next
equation is tried. If it succeeds, then the appropriate binding takes place,
and the next qualifier is matched, in the augmented environment.
and the next qualifier is matched.
```haskell
{-# LANGUAGE PatternGuards #-}
@ -4898,7 +4896,8 @@ Postfix Operators
-----------------
The postfix operators extensions allows user-defined operators that are placed
after expressions. For example we could define a postfix factorial function.
after expressions. For example, using this extension, we could define a postfix
factorial function.
```haskell
{-# LANGUAGE PostfixOperators #-}
@ -4933,9 +4932,9 @@ EmptyCase
---------
GHC normally requires at least one pattern branch in case statement this
restriction can be relaxed with `EmptyCase` language extension. The case
restriction can be relaxed with the `EmptyCase` langauge extension. The case
statement then immediately yields a ``Non-exhaustive patterns in case`` if
evaluated.
evaluated. For example, the following will compile using this language pragma:
```haskell
test = case of
@ -5010,7 +5009,8 @@ Record wild cards allow us to expand out the names of a record as variables
scoped as the labels of the record implicitly. The extension can be used to
extract variables names into a scope and/or to assign to variables in a record
drawing, aligning the record's labels with the variables in scope for the
assignment. The syntax introduced is the ``{..}`` pattern selector.
assignment. The syntax introduced is the ``{..}`` pattern selector as in the
following example:
~~~~ {.haskell include="src/04-extensions/wildcards_update.hs"}
~~~~
@ -5035,10 +5035,10 @@ g D {b, a} = a - b
PatternSynonyms
----------------
Suppose we were writing a typechecker, it would be very common to include a
distinct ``TArr`` term to ease the telescoping of function signatures, this is what
GHC does in its Core language. Even though technically it could be written in
terms of more basic application of the ``(->)`` constructor.
Suppose we were writing a typechecker, and we needed to parse type signatures.
One common solution would to include a ``TArr`` to pattern match on type
function signatures. Even though, technically it could be written in terms of
more basic application of the ``(->)`` constructor.
```haskell
data Type
@ -5049,8 +5049,9 @@ data Type
deriving (Show, Eq, Ord)
```
With pattern synonyms we can eliminate the extraneous constructor without
losing the convenience of pattern matching on arrow types.
With pattern synonyms we can eliminate the extraneous constructor without losing
the convenience of pattern matching on arrow types. We introduce a new pattern
using the `pattern` keyword.
```haskell
{-# LANGUAGE PatternSynonyms #-}
@ -5058,13 +5059,14 @@ losing the convenience of pattern matching on arrow types.
pattern TArr t1 t2 = TApp (TApp (TCon "(->)") t1) t2
```
So now we can write an eliminator and constructor for arrow type very naturally.
So now we can write an deconstructor and constructor for arrow type very
naturally.
~~~~ {.haskell include="src/04-extensions/patterns.hs"}
~~~~
Pattern synonyms can be exported from a module like any other definition by
prefixing them with the prefix ``pattern``.
prefixing them with the prefix ``pattern``.
```haskell
module MyModule (
@ -5079,10 +5081,10 @@ pattern Elt = [a]
DeriveFunctor
-------------
Many instances of functor over datatypes with simple single parameters and
trivial constructors are simply the result of trivially applying a functions
over the single constructor's argument. GHC can derive this boilerplace
automatically in deriving clauses if DeriveFunctor is enabled.
Many instances of functor over datatypes with parameters and trivial
constructors are the result of trivially applying a functions over the single
constructor's argument. GHC can derive this boilerplate automatically in
deriving clauses if `DeriveFunctor` is enabled.
~~~~ {.haskell include="src/04-extensions/derive_functor.hs"}
~~~~
@ -5091,16 +5093,15 @@ DeriveFoldable
--------------
Similar to how Functors can be automatically derived, many instances of Foldable
for types of kind `* -> *` have instances that simply derive the functions:
for types of kind `* -> *` have instances that derive the functions:
* `foldMap`
* `foldr`
* `null`
By simply deriving the boilerplate function over subexpression type with the
single parameter term. For instance if we have a custom rose tree and binary
tree implementation we can automatically derive the fold functions for these
datatypes automatically.
For instance if we have a custom rose tree and binary tree implementation we can
automatically derive the fold functions for these datatypes automatically for
us.
~~~~ {.haskell include="src/04-extensions/folding.hs"}
~~~~
@ -5130,9 +5131,8 @@ DeriveTraversable
Just as with Functor and Foldable, many `Traversable` instances for
single-paramater datatypes of kind `* -> *` have trivial implementations of the
`traverse` function which can be derived automatically. By enabling
`DeriveTraversable` we can use stock deriving to automatically derive these
instances.
`traverse` function which can also be derived automatically. By enabling
`DeriveTraversable` we can use stock deriving to derive these instances for us.
~~~~ {.haskell include="src/04-extensions/derive_traversable.hs"}
~~~~
@ -5140,12 +5140,11 @@ instances.
DeriveGeneric
-------------
Data types in Haskell can derived by GHC with the DeriveGenerics extension
whicch is able to define the entire structure of the Generic instance and
associated type families musically. See [Generics] for more details on what
these types mean.
Data types in Haskell can derived by GHC with the DeriveGenerics extension which
is able to define the entire structure of the Generic instance and associated
type families. See [Generics] for more details on what these types mean.
For example the simple custom List type:
For example the simple custom List type deriving Generic:
```haskell
{-# LANGUAGE DeriveGeneric #-}
@ -5240,12 +5239,12 @@ test = (id (Person 1), id (Animal 2), id (Animal 3))
OverloadedLabels
----------------
GHC 8.0 also introduced the OverloadedLabels extension which allows a limited
GHC 8.0 also introduced the `OverloadedLabels` extension which allows a limited
form of polymorphism over labels that share the same name.
To work with overloaded label types we need to enable several language
extensions to work with promoted strings and multiparam typeclasses that
underlay it's implementation.
To work with overloaded label types we also need to enable several language
extensions that allow us to use the promoted strings and multiparam typeclasses
that underlay its implementation.
```haskell
extract :: IsLabel "id" t => t
@ -5274,8 +5273,8 @@ main = do
print (#foo (MkT True False))
```
This is also used in more advanced libraries like [Selda] which do object
relational mapping between Haskell datatype fields and database columns.
This is used in more advanced libraries like [Selda] which do object relational
mapping between Haskell datatype fields and database columns.
See:
@ -5299,7 +5298,7 @@ used to compile a module.
#endif
```
To demarcate code based on the operating system compiled on.
It can also demarcate code based on the operating system compiled on.
```haskell
{-# LANGUAGE CPP #-}
@ -5319,7 +5318,7 @@ To demarcate code based on the operating system compiled on.
#endif
```
Or on the version of the base library used.
For another example, it can distinguish the version of the base library used.
```haskell
#if !MIN_VERSION_base(4,6,0)
@ -5327,10 +5326,10 @@ Or on the version of the base library used.
#endif
```
One can also use the CPP to emit Haskell source at compile-time. This is used in
some libraries which have massive boiler plate obligations. This can be abused
quite easily and doing this kind of compile-time string-munging is a last
resort.
One can also use the CPP extension to emit Haskell source at compile-time. This
is used in some libraries which have massive boiler plate obligations. Of
course, this can be abused quite easily and doing this sort of compile-time
string-munging should be a last resort.
TypeApplications
----------------
@ -5352,12 +5351,12 @@ DerivingVia
`DerivingVia` is an extension of `GeneraliazedNewtypeDeriving`. Just as newtype
deriving allows us to derive instances in terms of instances for the underlying
representation of the newtype, DerivingVia allows deriving instances instance by
representation of the newtype, DerivingVia allows deriving instances by
specifying a custom type which has a runtime representation equal to the desired
behavior to derive the instance for. The derived instance can then be `coerced`
to behave as if it were operating over the given type. This is a powerful new
mechanism that allows us to derive many typeclasses in terms of other
typeclasses.
behavior we're deriving the instance for. The derived instance can then be
`coerced` to behave as if it were operating over the given type. This is a
powerful new mechanism that allows us to derive many typeclasses in terms of
other typeclasses.
~~~~ {.haskell include="src/04-extensions/derive_via.hs"}
~~~~
@ -5365,8 +5364,8 @@ typeclasses.
DerivingStrategies
-------------------
Deriving has proven a powerful mechanism to add to the typeclass extension and
as such there have been a variety of bifurcations in it's use. Since GHC 8.2
Deriving has proven a powerful mechanism to add to typeclass extension and
as such there have been a variety of bifurcations in its use. Since GHC 8.2
there are now four different algorithms that can be used to derive typeclasses
instances. These are enabled by different extensions and now have specific
syntax for invoking each algorithm specifically. Turning on `DerivingStrategies`
@ -5378,7 +5377,7 @@ derivations.
* `newtype` - Deriving with [GeneralizedNewtypeDeriving].
* `via` - Deriving with [DerivingVia].
These can stacked and combined on top of a data or newtype declaration.
These can be stacked and combined on top of a data or newtype declaration.
```haskell
newtype Example = Example Int
@ -5410,8 +5409,8 @@ become deprecated in favor of others. Others are just considered misfeatures.
<hr/>
Type Classes
============
Type Class Extensions
=====================
Typeclasses are the bread and butter of abstractions in Haskell, and even out of
the box in Haskell 98 they are quite powerful. However classes have grown quite
@ -5453,7 +5452,7 @@ Whenever a typeclass method is invoked at a callsite, GHC will perform an
instance search over all available instances defined for the given typeclass
associated with the method. This instance search is quite similar to backward
chaining in logic programming languages. The search is performed during
compilation after all types in all modules are known as is performed *globally*
compilation after all types in all modules are known and is performed *globally*
across all modules and all packages available to be linked. The instance search
can either result in no instances, a single instance or multiple instances which
satisfy the conditions of the call site.
@ -5461,6 +5460,8 @@ satisfy the conditions of the call site.
Orphan Instances
----------------
TODO START HERE
Normally typeclass definitions are restricted to be defined in one of two
places:
@ -5470,7 +5471,7 @@ places:
These two restrictions restrict the instance search space to a system where a
solution (if it exists) can always be found. If we allowed instances to be
defined in any modules then we could potentially have multiple class instances
defined in multiple modules and search would be ambiguous.
defined in multiple modules and the search would be ambiguous.
This restriction can however be disabled with the `-fno-warn-orphans` flag.