Can I import a non-abstract type abstractly? - haskell

Suppose I have a module that contains a type:
module My where
data L a = Nil | Cons a (L a)
The module exports the concrete definition of My to allow for pattern matching etc.
Is it possible for another module, say Client to import My in a manner where L a
is abstract i.e. such that pattern matching on L a values is prohibited by the type-checker?

Yes; you just have to use the import list:
module Client where
import My (L)
ok :: L Int
ok = undefined
bad :: L Int
bad = Cons 3 Nil
bad2 :: L Int -> Int
bad2 (Cons i _) = i
bad2 Nil = 0
If you try to compile this, you'll get the following four errors:
Client.hs:8:10: Not in scope: data constructor `Cons'
Client.hs:8:17: Not in scope: data constructor `Nil'
Client.hs:11:10: Not in scope: data constructor `Cons'
Client.hs:12:9: Not in scope: data constructor `Nil'
If you did want to import the constructors, you would instead specify L(..), or L(Cons) to import Cons but not Nil.
For some other ways you can use the import statement, check out the HaskellWiki article on import (although the article doesn't mention importing data types and their constructors).

Yes, you may do
import My(L())
to import a type without importing any of its constructors. If you still wish to construct values of this type (but not pattern match), you must import functions for doing that construction (for example, by exporting such functions from My or by creating a utility module with such functions).
edit: Since you explicitly mentioned that you wanted a type-checking error, I should point out for completeness that this won't cause pattern-matching on Nil and Cons to be a type-checking error, but merely a scoping error.

Related

Cannot implement Foldable instance due to wrong kind

I am learning haskell and trying to make a pretty print program. At some point I want to get the length of a row (i.e. number of columns in that row). To be able to do that on my datatype I understand I have to implement Foldable, which relies on Monoid.
Previously my row was just a type alias for a list but for sake of learning I want to make this move
import System.IO
import System.Directory
import Control.Monad
import Data.Maybe
import Data.Monoid
import Data.Foldable
import Data.Functor
import Data.List.Split
type Field = String
data Row = Row [Field]
instance Monoid Row where
mempty = Row []
instance Foldable Row where
foldMap f (Row fs) = foldMap f fs
But I get the following compiler error (on ghci 8.0.2)
main.hs:20:19: error:
• Expected kind ‘* -> *’, but ‘Row’ has kind ‘*’
• In the first argument of ‘Foldable’, namely ‘Row’
In the instance declaration for ‘Foldable Row’
Now I am not familiar with what the kind of a datatype is. I was expecting this to simply defer to Row's only property of type List
When we have Foldable T, T must be a parametric type, i.e. we must be able to form types T Int, T String, etc.
In Haskell we write T :: * -> * for "a type parametrized over a type", since it resembles a function from types to types. The syntax * -> * is called the kind of T.
In your case, Row is not parametrized, it is a plain type, something of kind *, not * -> *. So, Foldable Row is a kind error. In a sense, a foldable must be a generic list-like container, not one that only carries Field as in your case.
You could instead define data Row a = Row [a], and use Row Field when you need that specific case.
Alternatively, you could try MonoFoldable Row from the mono-traversable package, but note that this is a more advanced option, involving type families. Do not take this path lightly before considering its consequences. It ultimately boils down to why you need a Foldable instance.
what is the "kind" of a datatype?
Types "of kind *" are types of things that can appear in a Haskell program.
Example: Int.
Not an example: Maybe.
a :: Int ; a = 1 can appear in a Haskell program but b :: Maybe ; b = Just 1 can't. It must be b :: Maybe Int ; b = Just 1, to be valid for it to appear in a Haskell program.
What is Maybe Int? It is a type of kind * just as Int is. So what is Maybe? It is a type of kind * -> *. Because Maybe Maybe is also invalid.
The type t appearing after the Maybe must itself be of kind * for Maybe t to be of kind *. Thus the kind of Maybe is * -> *.
Haskell now calls the kind * by new name, Type. Calling it Thing or something could have been more intuitive.

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.

Data type design in Haskell

Learning Haskell, I write a formatter of C++ header files. First, I parse all class members into a-collection-of-class-members which is then passed to the formatting routine. To represent class members I have
data ClassMember = CmTypedef Typedef |
CmMethod Method |
CmOperatorOverload OperatorOverload |
CmVariable Variable |
CmFriendClass FriendClass |
CmDestructor Destructor
(I need to classify the class members this way because of some peculiarities of the formatting style.)
The problem that annoys me is that to "drag" any function defined for the class member types to the ClassMember level, I have to write a lot of redundant code. For example,
instance Formattable ClassMember where
format (CmTypedef td) = format td
format (CmMethod m) = format m
format (CmOperatorOverload oo) = format oo
format (CmVariable v) = format v
format (CmFriendClass fc) = format fc
format (CmDestructor d) = format d
instance Prettifyable ClassMember where
-- same story here
On the other hand, I would definitely like to have a list of ClassMember objects (at least, I think so), hence defining it as
data ClassMember a = ClassMember a
instance Formattable ClassMember a
format (ClassMember a) = format a
doesn't seem to be an option.
The alternatives I'm considering are:
Store in ClassMember not object instances themselves, but functions defined on the corresponding types, which are needed by the formatting routine. This approach breaks the modularity, IMO, as the parsing results, represented by [ClassMember], need to be aware of all their usages.
Define ClassMember as an existential type, so [ClassMember] is no longer a problem. I doubt whether this design is strict enough and, again, I need to specify all constraints in the definition, like data ClassMember = forall a . Formattable a => ClassMember a. Also, I would prefer a solution without using extensions.
Is what I'm doing a proper way to do it in Haskell or there is a better way?
First, consider trimming down that ADT a bit. Operator overloads and destructors are special kinds of methods, so it might make more sense to treat all three in CmMethod; Method will then have special ways to separate them. Alternatively, keep all three CmMethod, CmOperatorOverload, and CmDestructor, but let them all contain the same Method type.
But of course, you can reduce the complexity only so much.
As for the specific example of a Show instance: you really don't want to write that yourself except in some special cases. For your case, it's much more reasonable to have the instance derived automatically:
data ClassMember = CmTypedef Typedef
| CmMethod Method
| ...
| CmDestructor Destructor
deriving (Show)
This will give different results from your custom instance – because yours is wrong: showing a contained result should also give information about the constructor.
If you're not really interested in Show but talking about another class C that does something more specific to ClassMembers – well, then you probably shouldn't have defined C in the first place! The purpose of type classes is to express mathematical concepts that hold for a great variety of types.
A possible solution is to use records.
It can be used without extensions and preserves flexibility.
There is still some boilerplate code, but you need to type it only once for all. So if you would need to perform another set of operations over your ClassMember, it would be very easy and quick to do it.
Here is an example for your particular case (template Haskell and Control.Lens makes things easier but are not mandatory):
{-# LANGUAGE TemplateHaskell #-}
module Test.ClassMember
import Control.Lens
-- | The class member as initially defined.
data ClassMember =
CmTypedef Typedef
| CmMethod Method
| CmOperatorOverload OperatorOverload
| CmVariable Variable
| CmFriendClass FriendClass
| CmDestructor Destructor
-- | Some dummy definitions of the data types, so the code will compile.
data Typedef = Typedef
data Method = Method
data OperatorOverload = OperatorOverload
data Variable = Variable
data FriendClass = FriendClass
data Destructor = Destructor
{-|
A data type which defines one function per constructor.
Note the type a, which means that for a given Hanlder "a" all functions
must return "a" (as for a type class!).
-}
data Handler a = Handler
{
_handleType :: Typedef -> a
, _handleMethod :: Method -> a
, _handleOperator :: OperatorOverload -> a
, _handleVariable :: Variable -> a
, _handleFriendClass :: FriendClass -> a
, _handleDestructor :: Destructor -> a
}
{-|
Here I am using lenses. This is not mandatory at all, but makes life easier.
This is also the reason of the TemplateHaskell language pragma above.
-}
makeLenses ''Handler
{-|
A function acting as a dispatcher (the boilerplate code!!!), telling which
function of the handler must be used for a given constructor.
-}
handle :: Handler a -> ClassMember -> a
handle handler member =
case member of
CmTypedef a -> handler^.handleType $ a
CmMethod a -> handler^.handleMethod $ a
CmOperatorOverload a -> handler^.handleOperator $ a
CmVariable a -> handler^.handleVariable $ a
CmFriendClass a -> handler^.handleFriendClass $ a
CmDestructor a) -> handler^.handleDestructor $ a
{-|
A dummy format method.
I kept things simple here, but you could define much more complicated
functions.
You could even define some generic functions separately and... you could define
them with some extra arguments that you would only provide when building
the Handler! An (dummy!) example is the way the destructor function is
constructed.
-}
format :: Handler String
format = Handler
(\x -> "type")
(\x -> "method")
(\x -> "operator")
(\x -> "variable")
(\x -> "Friend")
(destructorFunc $ (++) "format ")
{-|
A dummy function showcasing partial application.
It has one more argument than handleDestructor. In practice you are free
to add as many as you wish as long as it ends with the expected type
(Destructor -> String).
-}
destructorFunc :: (String -> String) -> Destructor -> String
destructorFunc f _ = f "destructor"
{-|
Construction of the pretty handler which illustrates the reason why
using lens by keeping a nice and concise syntax.
The "&" is the backward operator and ".~" is the set operator.
All we do here is to change the functions of the handleType and the
handleDestructor.
-}
pretty :: Handler String
pretty = format & handleType .~ (\x -> "Pretty type")
& handleDestructor .~ (destructorFunc ((++) "Pretty "))
And now we can run some tests:
test1 = handle format (CmDestructor Destructor)
> "format destructor"
test2 = handle pretty (CmDestructor Destructor)
> "Pretty destructor"

Error when trying to create a Data.List?

I am trying to create a list of type Pos (custom) but keep getting the following error:
Not in scope: type constructor or class `List'
Code:
import Data.List
type Pos = (Int, Int)
type PlayList = List Pos
The error comes up on the line where I define my type PlayList.
Any ideas? Using Haskell in EclipseFP
The list type is actually called [], so you'd want
type PlayList = [Pos]
Although you'll often see people write their own list implementation for playing with various techniques as
data List a = Nil | Cons a (List a)
which is isomorphic to (identical to except for name) the actual implementation of
data [a] = [] | a : [a]
Where Nil == [] and Cons == (:).

Overload built in function in Haskell

In Haskell, how can one overload a built in function such as !!?
I originally was trying to figure out how to overload the built in function !! to support by own data types. Specifically, !! is of the type:
[a] -> Int -> a
and I want to preserve it's existing functionality, but also be able to call it where its type signature looks more like
MyType1 -> MyType2 -> MyType3
I originally wanted to do this because MyType1 is like a list, and I wanted to use the !! operator because my operation is very similar to selecting an item from a list.
If I was overloading something like + I could just add an instance of my function to the applicable type class, but I don't think that is an option here.
I'm not convinced I actually even want to overload this function anymore, but I am still interested in how it would be done. Actually, comments on if overloading an operator such as !! is even a good idea would be appreciated as well.
In Haskell, nearly all operators are library-defined. Many of the ones you use the most are defined in the 'standard library' of the Prelude module that is imported by default. Gabriel's answer shows how to avoid importing some of those definitions so you can make your own.
That's not overloading though, because the operator still just means one thing; the new meaning you define for it. The primary method that Haskell provides for overloading, i.e. using an operator in such a way that it has different implementations for different types, is the type class mechanism.
A type class identifies a group of types that support some common functions. When you use those functions with a type, Haskell figures out the correct instance of the type class that applies to your usage and makes sure the correct implementation of the functions is used. Most type classes have just a few functions, some just one or two, that need to be implemented to make a new instance. Many of them offer a lot of secondary functions implemented in terms of the core ones as well, and you can use all of them with a type you make an instance of the class.
It so happens that others have made types that behave quite a bit like lists, and so there's already a type class called ListLike. I'm not sure exactly how close your type is to a list, so it may not be a perfect fit for ListLike, but you should look at it as it will give you a lot of capability if you can make your type a ListLike instance.
You can't actually overload an existing non-typeclass function in Haskell.
What you can do is define a new function in a new type class, which is general enough to encompass both the original function and the new definition you want as an overload. You can give it the same name as the standard function, and avoid importing the standard one. That means in your module you can use the name !! to get both the functionality of your new definition, and the original definition (the resolution will be directed by the types).
Example:
{-# LANGUAGE TypeFamilies #-}
import Prelude hiding ((!!))
import qualified Prelude
class Indexable a where
type Index a
type Elem a
(!!) :: a -> Index a -> Elem a
instance Indexable [a] where
type Index [a] = Int
type Elem [a] = a
(!!) = (Prelude.!!)
newtype MyType1 = MyType1 String
deriving Show
newtype MyType2 = MyType2 Int
deriving Show
newtype MyType3 = MyType3 Char
deriving Show
instance Indexable MyType1 where
type Index MyType1 = MyType2
type Elem MyType1 = MyType3
MyType1 cs !! MyType2 i = MyType3 $ cs !! i
(I've used type families to imply that for a given type that can be indexed, the type of the indices and the type of the elements automatically follows; this could of course be done differently, but going into that in more detail is getting side-tracked from the overload question)
Then:
*Main> :t (!!)
(!!) :: Indexable a => a -> Index a -> Elem a
*Main> :t ([] !!)
([] !!) :: Int -> a
*Main> :t (MyType1 "" !!)
(MyType1 "" !!) :: MyType2 -> MyType3
*Main> [0, 1, 2, 3, 4] !! 2
2
*Main> MyType1 "abcdefg" !! MyType2 3
MyType3 'd'
It should be emphasised that this has done absolutely nothing to the existing !! function defined in the prelude, nor to any other module that uses it. The !! defined here is a new and entirely unrelated function, which just happens to have the same name and to delegate to Prelude.!! in one particular instance. No existing code will be able to start using !! on MyType1 without modification (though other modules you can change can of course import your new !! to get this functionality). Any code that imports this module will either have to module-qualify all uses of !! or else use the same import Prelude hiding ((!!)) line to hide the original one.
Hide the Prelude's (!!) operator and you can define your own (!!) operator:
import Prelude hiding ((!!))
(!!) :: MyType1 -> MyType2 -> MyType3
x !! i = ... -- Go wild!
You can even make a type class for your new (!!) operator if you prefer.

Resources