Overlapping Pattern Match warning with custom data types - haskell

I'm translating several programs from Standard ML to Haskell for a class, and I'm confused about the way Haskell is parsing this pattern matching.
I have this data type:
data Term = A | B
| F Term | G Term | H Term Term
| Var String
deriving (Show)
And this is part of the function I am defining:
unify :: [(Term, Term)] -> Bool
-- argument represents a list of term equations,
-- result indicates whether they have a solution
unify nil = True
unify ((A, A):eqns) = unify eqns
unify ((B, B):eqns) = unify eqns
unify ((F(t1), F(t2)):eqns) = unify((t1,t2):eqns)
unify ((G(t1), G(t2)):eqns) = unify((t1,t2):eqns)
unify ((H s1 t1, H s2 t2):eqns) = unify((s1,s2):(t1,t2):eqns)
unify ((Var v1, t):eqns) =
(case t of
Var v2 -> if v1 == v2 then unify(eqns)
else unify(map (substEqn v1 t) eqns)
_ -> unify(map (substEqn v1 t) eqns))
unify ((t, Var v):eqns) = unify(map (substEqn v t) eqns)
unify _ = False
ghci gives me this output when I import the module:
Warning: Pattern match(es) are overlapped
In an equation for `unify':
unify ((A, A) : eqns) = ...
unify ((B, B) : eqns) = ...
unify ((F (t1), F (t2)) : eqns) = ...
unify ((G (t1), G (t2)) : eqns) = ...
...
I certainly understand how pattern matching works, but I don't understand why Haskell considers these four arguments identical. They are different data types, so shouldn't they not be equivalent patterns? This worked in Standard ML, but something must be lost in translation. Thanks for the help!

I am not sure what nil is (in the first pattern), but I assume you have the empty list in mind. If that is the case, replacing it with [] will do the trick and your pattern matching problem goes away.

Related

How do I get 'unpredictable' overloading on a return type working in Haskell?

I have some type instances. Let's call them A, B, and C. They all are instances of typeclass X. Now I would like to create a seperate function create that creates an instance of A, B or C given some input (let's say a string). The type system cannot know what input is going to give what type. That's the thing Haskell doesn't like, and I think I know the answer, but I want to be sure. The current error I'm getting is:
• Couldn't match expected type ‘c’ with actual type ‘GCCCommand’
‘c’ is a rigid type variable bound by
the type signature for:
compiler :: forall c. CompilerCommand c => String -> c
at src/System/Command/Typed/CC.hs:29:1-44
• In the expression: gcc path
In an equation for ‘compiler’:
compiler path
| exe == "g++" || exe == "gcc" || exe == "cc" || exe == "cpp"
= gcc path
where
exe = takeFileName path
• Relevant bindings include
compiler :: String -> c
(bound at src/System/Command/Typed/CC.hs:31:1)
Does that mean, as I suspect, that it is not possible to overload on return type in this particular case because the compiler can't know upfront how the data will look in memory? How would you go to implement this function? I was thinking about creating something like the following:
data SuperX = SuperA A | SuperB B | SuperC C
create :: String -> SuperX
-- create can now be implemented
instance X SuperX where
-- a lot of boilerplate code ...
However, the boilerplate code suggests that it can be done better. Is this really the best way for doing it?
It depends what you need to do with it.
If your later processing doesn't care if it gets an A, a B, or C, just that it gets something that implements X...
restOfProgram :: X a => a -> ThingIWantToCompute
Then you could use continuation passing:
parseABC :: (X a => a -> r) -> String -> Maybe r
parseABC f "A" = Just (f A)
parseABC f ('B':xs) = Just (f (B xs))
parseABC f ('C':xs) = Just (f (C (read xs)))
parseABC _ _ = Nothing
Or an existential data wrapper:
data SomeX where
SomeX :: X t => t -> SomeX
parseABC :: String -> Maybe SomeX
parseABC "A" = Just (SomeX A)
parseABC ('B':xs) = Just (SomeX (B xs))
parseABC ('C':xs) = Just (SomeX (C (read xs)))
parseABC _ _ = Nothing
restOfProgram' :: SomeX -> ThingIWantToCompute
restOfProgram' (SomeX t) = restOfProgram t
If the later processing has different paths for A, B or C, you probably want to return a sum type like SuperX.

Getting an error: parse error on input ‘Just’

data Type = Nat | Bool | App Type Type | Var String
deriving (Eq, Show)
type Substitution = [(String, Type)]
apply :: Substitution -> Type -> Type
apply s Nat = Nat
apply s Bool = Bool
apply s Var c = case (lookup s c) of
Nothing -> (Var c)
Just v -> v
But the compilers give me the error "error: parse error on input ‘Just’
"
What am I doing wrong?
I can not reproduce the error locally, so my guess is that you used tabs an spaces, if you however copy paste your code into the editor, it should "work". In that case we however receive another error:
GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help
[1 of 1] Compiling Main ( tmp.hs, interpreted )
tmp.hs:7:1: error:
Equations for ‘apply’ have different numbers of arguments
tmp.hs:7:1-17
tmp.hs:(9,1)-(11,29)
Failed, modules loaded: none.
This is due to the fact that you write:
apply s Var c = -- ...
and Haskell assumes that you here wrote three parameters: s, Var, and c, but the c of course belongs to the Var data constructor. We can fix this with a pair of brackets. Furthermore you call lookup in the wrong way: lookup has type lookup :: Eq a => a -> [(a, b)] -> Maybe b, so the first argument is the key (here c), and the second argument is the lookup table s. So we can fix this with:
apply :: Substitution -> Type -> Type
apply s Nat = Nat
apply s Bool = Bool
apply s (Var c) = case (lookup c s) of
Nothing -> (Var c)
Just v -> v
Note that you can get rid of the case pattern matching, and use for instance fromMaybe :: a -> Maybe a -> a instead:
import Data.Maybe(fromMaybe)
apply :: Substitution -> Type -> Type
apply s Nat = Nat
apply s Bool = Bool
apply s d#(Var c) = fromMaybe d (lookup c s)
We can furthermore group the Nat and Bool case together:
import Data.Maybe(fromMaybe)
apply :: Substitution -> Type -> Type
apply s d#(Var c) = fromMaybe d (lookup c s)
apply s t = t
This given of course that in case the Type is not a Var c pattern, we should return that Type.
Perhaps you need to call apply recursively as well, since the substitution can result into another Var (and thus you have to do extra lookups). This will however change the function semantically (!), so I am not sure if that is a requirement.
I got an error about the number of args to apply and about the types in lookup, but this code typechecks:
data Type = Nat | Bool | App Type Type | Var String
deriving (Eq, Show)
type Substitution = [(String, Type)]
apply :: Substitution -> Type -> Type
apply s Nat = Nat
apply s Bool = Bool
apply s (Var c) = case (lookup c s) of
Nothing -> (Var c)
Just v -> v
Note the parentheses around Var c and the order of lookup c s

Understanding function signature

I was reading a paper and one of the most fundamental parts of it is the following function, written in Haskell:
fixP :: Eq a => (Parser a -> Parser a) -> Parser a
fixP h x = fixS f
where f s = h p x
where p y = if x == y then s
else fixP h y
My Haskell is rusty. As I understand it fixP takes 1 argument which is a function Parser a -> Parser a, where a is constrained to have equality defined. However the pattern matches 2 arguments, h and x. What is x referring to?
Additional type signatures involved:
type Parser a = State -> Set (a,State)
type State = String
type Set a = [a]
fixS :: Eq a => (Set a -> Set a) -> Set a
After reading and understanding the answer and for anyone interested; here's the same function written in javascript:
function fixP(h) {
return function(x) {
var f = function(s) {
var p = function(y) {
if(x == y) {
return s;
} else {
return fixP(h)(y);
}
};
return h(p)(x);
};
return fixS(f);
};
}
Note that fixP h has type Parser a. Since Parser a is a synonym for State -> Set (a, State), we see that fixP h is in fact a function:
(fixP h) :: State -> Set (a, State)
We can therefore apply this function to some argument x of type State. That looks like (fixP h) x. Since function application is left associative , (fixP h) x is the same as fixP h x.
In words: To define what fixP is, we define what it does to arguments, i.e. we define what fixP h is. Since fixP h is itself a function, we need to define it. We define it by specifying what it does to arguments, i.e. we define what (fixP h) x is. Left associativity of function application means the latter can be written fixP h x.
As to the question "what's x?": Its type is State, so it smells like some sort of parser state, which according to the type synonyms you gave is a string. Exactly what that string's role is, though, is not clear just from the types :)
Simple explanation: Parser a is a type like this:
type Parser a = (String -> a)
This code then
module Main where
type NT a = (Int -> a)
f :: (NT a -> NT a) -> NT a
f h x = undefined
g :: NT Double
g 0 = 0.0
g _ = 1.0
main = undefined
typechecks well.

Using fsharp-typeclasses to make a function that works on arbitrary monads

I'm trying to implement composM from the paper A pattern for almost compositional functions which accepts an arbitray monad and works on it. In Haskell the code would be:
data Expr =
| Var String
| Abs String Expr
composExprM :: (Monad m) => (Expr -> m Expr) -> Expr -> m Expr
composExprM f e =
case e of
Abs n e -> f e >>= (\e' -> return $ Abs n e')
_ -> return e
I tried using fsharp-typeclasses with the code below:
type Expr =
| Var of string
| Abs of string * Expr
let rec composExprM f e = match e with
| Abs (n, e) -> f e >>= (fun e' -> return' <| Abs (n, e'))
| Var _ -> return' e
But I get type inference errors:
> Could not resolve the ambiguity inherent in the use of the operator 'instance' at or near this program point. Consider using type annotations to resolve the ambiguity.
> Type constraint mismatch when applying the default type 'obj' for a type inference variable. No overloads match for method 'instance'. The available overloads are shown below (or in the Error List window). Consider adding further type constraints
> Possible overload: 'static member Return.instance : _Monad:Return * Maybe<'a> -> ('a -> Maybe<'a>)'. Type constraint mismatch. The type
obj
is not compatible with type
Maybe<'a>
The type 'obj' is not compatible with the type 'Maybe<'a>'.
> etc.....
Is what I'm trying to achieve possible with fsharp-typeclasses? Or do I have to restrict the function to only use a specific monad?
Keep in mind that polymorphic functions using this technique should be inline, that's where the "magic" resides.
So, just add the inline keyword after let rec and it will compile.
Please let me know if the function behaves as expected. I will have a look at that paper later.
In the samples you will find many functions defined to work with any Monad.
That was the main motivation when I started this project.

Haskell Data.List.Class and syntax

I am trying to read the source code for the Haskell package Data.List.Class. (List-0.4.2). But I am stuck with some of the syntax.
Right at the beginning, it reads:
data ListItem l a =
Nil |
Cons { headL :: a, tailL :: l a }
I am not familiar with the syntax of the 3rd line. I guess that this last line is equivalent to Cons a (l a) ??. But I am not really sure. I noticed that the header of the file says: {-# LANGUAGE FlexibleContexts, TypeFamilies #-}.
Then as I go on, there is a strange use of the type statement: type ItemM l :: * -> *, which I couldn't understand.
Data.List.Class
-- | A class for list types. Every list has an underlying monad.
class (MonadPlus l, Monad (ItemM l)) => List l where
type ItemM l :: * -> *
runList :: l a -> ItemM l (ListItem l a)
joinL :: ItemM l (l a) -> l a
cons :: a -> l a -> l a
cons = mplus . return
Can anyone help explain what these mean? I have a perfect understanding of Data.List, but this type class thing is not really clear to me.
Also I searched about wiki's, examples, and/or tutorials for using Data.List.{Class,Tree}, but there does not seem to be any, except the comments that come with the code. Any pointers here?
Thanks.
-- update --
The first answer (#Chris) helped me understand the Kind signature and the Record Syntax, which is really helpful. However, I still cannot make sense out of that piece of code overall in terms of how it captures/defines the behavior of a List and what value it adds to the familiar Data.List definitions. Here are some further details, where there are only two instance statements. Also the Identity term comes from import Data.Functor.Identity (Identity(..)). Can you please help explain what this is type class do to capture the characteristics of a list as we normally know it? Again, I searched it online but there is really no documentation for Data.List.Class except the code itself. Anyone knows?
Also, is there another example use of the type statement in the typeclass constraint similar to what's in this example? I searched learnyouahaskell.com/ (#Landei) but couldn't find such an example. I am assuming that the usage of type here is similar to how you would use typedef's in C++ templates to define 'functions on types', right?
Thanks again.
instance List [] where
type ItemM [] = Identity
runList [] = Identity Nil
runList (x:xs) = Identity $ Cons x xs
joinL = runIdentity
cons = (:)
instance Functor m => Functor (ListItem m) where
fmap _ Nil = Nil
fmap func (Cons x xs) = Cons (func x) (fmap func xs)
Record Syntax
This
data ListItem l a = Nil | Cons { headL :: a, tailL :: l a }
is called record syntax. You're correct when you guess that the structure is the same as if you'd typed
data ListItem l a = Nil | Cons a (l a)
However, you also get the two accessor functions:
headL :: ListItem l a -> a
headL (Cons a _) = a
tailL :: ListItem l a -> l a
tailL (Cons _ as) = as
Record syntax is syntactic sugar - here it saves you around 4 lines of code. You can pattern match in the normal way, as in the code directly above this paragraph, or you can use the record syntax in the pattern match:
safeHeadL :: ListItem l a -> Maybe a
safeHeadL Nil = Nothing
safeHeadL (Cons {headL = a}) = Just a
Again, this is desugared into standard pattern matching.
Kind Signatures
This
class (MonadPlus l, Monad (ItemM l)) => List l where
type ItemM l :: * -> *
runList :: l a -> ItemM l (ListItem l a)
joinL :: ItemM l (l a) -> l a
cons :: a -> l a -> l a
cons = mplus . return
is a type family declaration. The line
type ItemM l :: * -> *
is a kind signature. When we say something has kind *, we mean that it's a base type, like Int or Float. To say that something has kind * -> * means that it is a type constructor, i.e. it takes a type and returns another type.
The Maybe type constructor has this kind signature:
Maybe :: * -> *
Remember that Maybe on its own isn't a type. It has to be given a type, and then it returns a type. Give it Int and you get Maybe Int. Give it Double and you get Maybe Double.
The type constructor ItemM l takes a type parameter (of kind *) and returns something of kind *. Note that since l is of kind *, you have
ItemM :: * -> * -> *
i.e. ItemM takes two types, and returns a type (equivalently, it takes one type and returns a unary type constructor).
By including the type declaration in the class, you impose the constraint that in all instances of the class, the l in ItemM l has to match up with the l in List l. It's impossible to create an instance of the class where these don't match up.

Resources