Import a type family that is an operator in Haskell - haskell

GHC.TypeNats exports type family of the following signature:
type family (m :: Nat) + (n :: Nat) :: Nat
How can I import it explicitly? import GHC.TypeNats((+)) does not work, because it says that GHC.TypeNats does not export (+)...
Everything compiles okay when I import whole module implicitly, but this really is not what I want to have in my code.
I am using GHC 8.6.5

From the manual:
There is now some potential ambiguity in import and export lists; for example if you write import M( (+) ) do you mean the function (+) or the type constructor (+)? The default is the former, but with ExplicitNamespaces (which is implied by TypeOperators) GHC allows you to specify the latter by preceding it with the keyword type, thus:
import M( type (+) )

Related

haskell hide import of star-operator

I have:
import qualified GHC.Types as T hiding (Module, (*))
import GHC.TypeNats hiding ((*))
but when I try to define a (*)-operator, it fails:
{-# INLINE (*) #-}
infixl 7 *
(*) :: r -> r -> r
(*) = undefined
with
error:
Ambiguous occurrence ‘*’
It could refer to either ‘T.*’,
imported qualified from ‘GHC.Types’ at ...
or ‘*’,
imported from ‘GHC.TypeNats’ at ...
|
1277 | infixl 7 *
EDIT: the description is currently not reproducible. I will update the question as soon as I can.
Neither GHC.Types nor GHC.TypeNats have a (*) export. They both have a type (*) export. Usually, you can distinguish between term-level (*) and type-level (*) by context, but this is not true in export/import lists. Instead, term-level is taken as default, and you must explicitly say you want to hide the types.
import qualified GHC.Types as T hiding (Module, type (*))
import GHC.TypeNats hiding (type (*))
The reason Module remains unadorned is because the capitalization means it must be either a type, a constructor, or a pattern synonym. Constructors must occur inside grouping () next to their data types, and pattern synonyms must be set apart with pattern, so the Module above is taken to refer to the data type (hiding the data type also hides all of its constructors).
The reason you did not get an error when you tried to hide something that didn't exist is because hiding was designed so that, if the imported module ever stopped exporting something you hid, your module would not fail to compile. After all, the only reason you referenced that thing was to say that you weren't going to reference that thing.

Hide a constructor but not the type on import

I've got an internal module I'd like to provide an external API for
module Positive.Internal where
newtype Positive a = Positive { getPositive :: a }
deriving (Eq, Ord)
-- smart constructor
toPositive :: (Num a, Ord a) => a -> Maybe (Positive a)
toPositive a | a <= 0 = Nothing
| otherwise = Just $ Positive a
-- ...
I want to hide the dumb constructor, and replace it with a unidirectional
pattern so users can still pattern match values, they just have to use the smart constructor to use new values.
Since I want the pattern and the dumb constructor to use the same name, I need to hide the dumb constructor to prevent namespace clashes.
However, since the dumb constructor and the type share names, it's a little tricky to import the everything BUT the dumb constructor.
Currently I'm doing this, which works ok:
{-# LANGUAGE PatternSynonyms #-}
module Positive
( module Positive.Internal, pattern Positive
) where
import Positive.Internal (Positive())
import Positive.Internal hiding (Positive)
import qualified Positive.Internal as Internal
pattern Positive :: a -> Positive a
pattern Positive a <- Internal.Positive a
I could simplify my imports by just using the qualified import, but I'm curious.
Is there a way to, in a single import statement, import all of Positive.Internal except the dumb constructor?
I tried hiding (Positive(Positive)), but that hid both the type and the dumb constructor. I've poked about the wiki, but I haven't noticed any way to differentiate between constructors and types in hiding lists.
Correct me if I am wrong, but I am almost certain this is what you are looking for:
{-# LANGUAGE PatternSynonyms #-}
module Positive
( module Positive.Internal, pattern Positive, foo
) where
import Positive.Internal hiding (pattern Positive)
import qualified Positive.Internal as Internal (pattern Positive)
pattern Positive :: a -> Positive a
pattern Positive a <- Internal.Positive a
foo :: Positive Int
foo = Internal.Positive 5
Internal module stays the same way as it is defined so far. And for the sake of example:
module Negative where
import Positive
bar :: Maybe Int
bar = getPositive <$> toPositive 6
Let's double check in GHCi:
Prelude> :load Negative
[1 of 3] Compiling Positive.Internal ( Positive/Internal.hs, interpreted )
[2 of 3] Compiling Positive ( Positive.hs, interpreted )
[3 of 3] Compiling Negative ( Negative.hs, interpreted )
Ok, modules loaded: Negative, Positive, Positive.Internal.
*Negative> bar
Just 6
*Negative> getPositive foo
5
*Negative> :i Positive
newtype Positive a = Positive.Internal.Positive {getPositive :: a}
-- Defined at Positive/Internal.hs:3:1
instance [safe] Ord a => Ord (Positive a)
-- Defined at Positive/Internal.hs:4:17
instance [safe] Eq a => Eq (Positive a)
-- Defined at Positive/Internal.hs:4:13
*Negative> :t Positive
<interactive>:1:1: error:
• non-bidirectional pattern synonym ‘Positive’ used in an expression
• In the expression: Positive

Instance Binary of PSQueue

I have want to make a Binary instance for a Priority Sorted Queue from containers. I am using lts-7.0
If Test.hs is
import Data.Binary
import Data.PSQueue
instance Binary a => Binary (PSQ a Int)
running
stack ghci
:set -XFlexibleInstances
:load Test.hs
results in confusing error messages.
~> :load Test.hs
[1 of 1] Compiling Main ( Test.hs, interpreted )
Test.hs:4:10: warning: [-Wdeferred-type-errors]
• Could not deduce (GHC.Generics.Generic (PSQ a Int))
arising from a use of ‘binary-0.8.3.0:Data.Binary.Class.$dmput’
from the context: Binary a
bound by the instance declaration at Test.hs:4:10-39
• In the expression: binary-0.8.3.0:Data.Binary.Class.$dmput
In an equation for ‘put’:
put = binary-0.8.3.0:Data.Binary.Class.$dmput
In the instance declaration for ‘Binary (PSQ a Int)’
Test.hs:4:10: warning: [-Wdeferred-type-errors]
• Could not deduce (GHC.Generics.Generic (PSQ a Int))
arising from a use of ‘binary-0.8.3.0:Data.Binary.Class.$dmget’
from the context: Binary a
bound by the instance declaration at Test.hs:4:10-39
• In the expression: binary-0.8.3.0:Data.Binary.Class.$dmget
In an equation for ‘get’:
get = binary-0.8.3.0:Data.Binary.Class.$dmget
In the instance declaration for ‘Binary (PSQ a Int)’
Ok, modules loaded: Main
How can I get GHC to automatically derive the Binary instance of PSQ a Int?
You unfortunately will need to actually write your own Binary instance for this. On the plus side, that is pretty easy in this case:
import Data.Binary (put, get)
import Data.PSQueue (toAscList, fromAscList, (:->))
instance (Binary a, Binary b, Ord a, Ord b) => Binary (PSQ a b) where
put = put . fmap (\(k :-> v) -> (k,v)) . toAscList
get = fromAscList . fmap (\(k,v) -> k :-> v) <$> get
All this does is convert the priority queue to an ascending list of key-value tuples before/after converting it to/from binary.
Why can't GHC do the work for me?
For GHC to work its magic of deriving the right Binary instance for you, it relies on a special class called Generic that supplies high level information about the data contained in the different constructors. This class is derived (like Read, Show, Eq, etc.) with the DeriveGeneric flag enabled. However, since PSQ does not derive Generic, we might be stuck.
Normally though, there is another trick we can pull: enabling StandaloneDeriving lets us derive as usual, but seperately from the data definition:
deriving instance (Generic (PSQ k v))
But that does require that the constructors of PSQ k v be public (which they are not in this case), so we really can do nothing to derive Generic (PSQ k v). At this point, it is so much simpler to simply write the instance.

How to Define Typeclass Synonyms

In an attempt to make a sane(r) alternative to Haskell's numeric type system, the devs of numeric-prelude slipped up and decided to name all of their type classes C. Aside from making the docs totally confusing, this means that I have to fully qualify all uses of the typeclasses:
import qualified Algebra.Additive (C)
import qualified Algebra.Ring (C)
...
newtype Foo a = Foo a
instance (Algebra.Additive.C a) => Algebra.Additive.C (Foo a) where ...
myadd :: (Algebra.Additive.C a) => a -> a -> a
myadd a b = ...
Also, since NumericPrelude has finer grained typeclasses, I usually have to import several different NumericPrelude modules. I can simplify this a little by defining top-level constraint synonyms:
{-# LANGUAGE ConstraintKinds #-}
module NPSynonyms (Additive) where
import qualified Algebra.Additive (C)
type Additive a = (Algebra.Additive.C a)
which allows me to make sane functions:
myadd :: (Additive a) => a -> a -> a
myadd a b = ...
However, when I need to define an instance, I still have to (also) import the original NumericPrelude class:
{-# LANGUAGE ConstraintKinds #-}
import NPSynonyms
import Algebra.Additive (C)
newtype Foo a = Foo a
instance (Additive a) => Algebra.Additive.C (Foo a) where ...
So instead of making Additive a type synonym with kind Constraint, what I'd really like is to define a typeclass synonym for the typeclass Algebra.Additive.C. Is there any way to do this in GHC 7.8, or is there any sane alternative?
you have to fully qualify
No, not fully qualify. Consider:
import qualified Algebra.Additive as Add
myadd :: Add.C a => a -> a -> a
That looks fairly readable to me.
EDIT:
Also consider making a superclass and treating that as an alias:
class (Add.C a, Ring.C a) => Num a where
instance Num Int
instance Num Word

Haskell Import error: Not in scope

I have written this code:
import GHC.Float
next :: GHC.Float -> GHC.Float-> GHC.Float
next n x = (x + n / x) / 2
And I am getting the following error:
numerical.hs:3:9:
Not in scope: type constructor or class `GHC.Float'
numerical.hs:3:22:
Not in scope: type constructor or class `GHC.Float'
numerical.hs:3:34:
Not in scope: type constructor or class `GHC.Float'
The module imports without any problem, so I'm not sure if I'm referring to it with the wrong name or if the standard Float module is the same as the IEEE GHC.Float one and there's no need to explicitly import it.
I tried doing an import GHC.Float as Fl with no success--got the same type error on Fl.
I'm just starting Haskell (obviously), so any help is appreciated!
You don't have to import GHC.Float manually, you can just write Float, like so
next :: Float -> Float -> Float
next n x = (x + n / x) / 2
GHC implicitly imports a module called Prelude in every source file you have. Prelude includes a lot of handy types, functions, and other things that are used as the "built-ins" of the language. Types like Int, Float, Maybe, IO, and functions like head, +, /, and more.
You can test to see if a floating point number is an IEEE floating point with the function isIEEE from the GHC.Float module:
import GHC.Float
main = do
putStr "1.0 is an IEEE floating point: "
print $ isIEEE (1.0 :: Float)
If you run this, it will print True
I should have also mentioned that the reason why your code didn't compile earlier is because when you import a module with just import, everything from it comes into scope. You can force it to be qualified by using import qualified, here's a few examples:
import GHC.Float -- Everything now in scope
import qualified Data.Maybe -- Have to use full name
import qualified Data.List as L -- aliased to L
main = do
-- Don't have to type GHC.Float.isIEEE
print $ isIEEE (1.0 :: Float)
-- Have to use full name
print $ Data.Maybe.isJust $ Nothing
-- Uses aliased name
print $ L.sort [1, 4, 2, 5, 3]

Resources