I understand that ..
can be used in ranges--i.e., [1..3] == [1,2,3]
, and [10..]
is an infinite list starting at 10.
However, recently I've started seeing these double dots inside brackets too. Either as (..)
or {..}
.
For example, an import statement can read
import Colog (HasLog (..))
My first intuition here is to think that this means that HasLog has several components and we are explicitly importing all of them. But how does that differ from simply importing HasLog, without the (..)
?
Further, how does (..)
differ from {..}
?
It's merely an infix synonym for fmap , so you can write e.g. Prelude> (*2) <$> [1.. 3] [2,4,6] Prelude> show <$> Just 11 Just "11" Like most infix functions, it is not built-in syntax, just a function definition. But functors are such a fundamental tool that <$> is found pretty much everywhere.
Haskell Language QuickCheck Using implication (==>) to check properties with preconditions.
in goes along with let to name one or more local expressions in a pure function.
(..)
and {..}
are both ways to bring names associated with data types in scope, but they're very different and used in different contexts.
The (..)
syntax is specifically used for import
and export lists. It's part of the syntax for declaring which constructors and/or record fields of a data type you want to import/export. For example, if I have a module
module FooM where
data Foo = F0 | F1 | F2
data Bar = Bar { b0 :: Int, b1 :: Char }
then this compiles
import FooM ( Foo(F1,F2), Bar(b1) )
fu = F1
ba = b1
but this doesn't
import FooM ( Foo(F1,F2) )
fu = F0
because I've only imported the F1
and F2
constructors, not F0
. If I write
import FooM ( Foo(..), Bar(..) )
fu = F0
ba = b0
it also works, because this imports all constructors and record labels. By contrast, with
import FooM ( Foo )
fu = F0
you don't import any constructors or record fields at all, but only Foo
as an opaque type, so here fu = F0
also won't compile. (This often exploited in export lists, if you want the inner structure of a data type to be “private” and only manipulable with utility functions, smart constructors etc..)
{..}
is part of the RecordWildCards
extension. In a nutshell, it turns the names of all record labels that would apply to a parameter into locally-scoped variables.
I would advice against using this, it's one of those extensions that tried to address the shortcomings of Haskell's record system – with IMO not much success. Better to either use records in the traditional way, or auto-generate some lenses and use these to completely avoid the record issues.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With