The Type signature lacks an appropriate binding [Haskell] - haskell

I have been googling around to find the answer, and even came to a few questions asked here. It seems that this is an ambiguous error and I can't figure out how to solve it in my instance.
The offending code is below:
pos :: (Eq a) => [a] -> a -> Int
pos [] _ = -1
pos (x:xs) y
| not $ elem y (x:xs) = -1
| x == y = 0
| otherwise = 1 + pos xs y
-- Get the same element from another range as one element of the first range.
refPos :: (Eq a) => [a] -> [b] -> a -> b
refPos r1 r2 e1 = r2 !! (r1 `pos` e1)
letterNumber :: (Eq a, Char a) => a -> Int
lettNumber x = refPos ['a'..'z'] [0..25] x
The text of the exact error is:
15:1 The type signature for letterNumber lacks an accompanying binding.
Originally the type signature I put was Char -> Int, but that didn't work (it said something about Eq, but I'm too new too Haskell to interpret it properly). So I changed the type signature to have an Eq class constraint. If someone can point out what is wrong or a workaround, it would be greatly appreciated as this is a doorstop problem to a project I'm working on.

You provide a type signature for letterNumber, but then provide a binding for lettNumber. Note the missing er.
Just rename lettNumber to letterNumber, to match the spelling in the type signature.
Also, the correct type signature for letterNumber is
letterNumber :: Char -> Int

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

Converting types in Haskell

I'm working on a conversion problem for homework, and am a complete Haskell newbie, so bear with me. On one of them, it asks us to attempt to get the type of a function to be:
fc :: (Bool, [Char]) -> Int -> Integer -> [Bool]
Without worrying about what the actual function does or anything. These functions will not be run, it is just a test to see if we can convert types correctly. So far the furthest I can get is this:
fc :: (Bool, [Char]) -> Int
fc (x, y) = ord (head y)
Where I am turning it into an Int. When I try to turn it into an Integer using the toInteger function, it gives me:
Couldn't match expected type `Int -> Integer'
with actual type `Integer'
In the return type of a call of `toInteger'
Probable cause: `toInteger' is applied to too many arguments
In the expression: toInteger (ord (head y))
Any tips for the new guy?
Edit:
What I have been trying, for reference, is:
fc :: (Bool, [Char]) -> Int -> Integer
fc (x, y) = toInteger (ord (head y))
And I am getting the error above.
Your type signature is wrong. If you convert something you can't write it into the type signature. Only the last one is the return type. The others are parameter types.
Follow these:
fc::(Bool,[Char])->Integer
fc (x,y) = toInteger . ord . head $ y
fc::(Bool,[Char])->Int->Integer--
fc (x,y) n = if n == w then n else w
where w = toInteger . ord . head $ y
Edit:
The others mentioned currying what is absolutely correct if your teacher expect it. But the conversions doesn't take place in the type sign.
As n.m. says, the idea this is getting at is called currying. Basically, in Haskell, any function takes a single value and returns a single value: a -> b.
So, given this restriction, how can we implement functions like addition, which need two parameters? The answer is that we implement a function which takes a number, and returns another function which takes a number and returns a number. Laying it out this way might clarify things:
add :: Int -> Int -> Int
add x = f where f y = x + y
(which is equivalent to add x y = x + y, as well as add = (+)).
In your case, you should read the error carefully: Couldn't match expected type Int -> Integer with actual type Integer In the return type of a call of toInteger means that Haskell is expecting fc to return a value of type Int -> Integer, because that's what your type signature says, but the definition you've provided will always produce a value of type Integer.

Data initialization and data members change in Haskell

I'm new to Haskell and I cannot figure out how you declare a "Data" type and how you can initialize a variable with that type. I'd also like to know how can I change the values of certain members of that variable. For exaple :
data Memory a = A
{ cameFrom :: Maybe Direction
, lastVal :: val
, visited :: [Direction]
}
Direction is a Data type that contains N,S,E,W
val is a Type int
init :: Int -> a
init n = ((Nothing) n []) gives me the following error:
The function `Nothing' is applied to two arguments,
but its type `Maybe a0' has none
In the expression: ((Nothing) n [])
In an equation for `init': init n = ((Nothing) n [])
how can I fix this ?
UPDATE: That did it, thank you very much, but now i have another issue
move :: val -> [Direction] -> Memory -> Direction
move s cs m | s < m.lastVal = m.cameFrom
| ...
this gives me the following error:
Couldn't match expected type `Int' with actual type `a0 -> c0'
Expected type: val
Actual type: a0 -> c0
In the second argument of `(<)', namely `m . lastVal'
In the expression: s < m . lastVal
UPDATE 2: Again, that helped me a lot, thank you very much
Also, I have another question (sorry for being such a bother)
How do I adress only an element of a type
For example if I have
Type Cell = (Int, Int)
Type Direction = (Cell, Int)
how do I proceed if I want to compare a Cell variable with the Cell element of a Direction variable?
As to the update. The syntax
m.lastVal
and
m.cameFrom
is not what you want. Instead
move s cs m | s < lastVal m = cameFrom m
accessors are just functions, so used in prefix form. The . in Haskell is used for namespace resolution (which is not path dependent) and for function composition
(.) :: (b -> c) -> (a -> b) -> a -> c
(.) f g x = f (g x)
To initialise:
init :: Int -> Memory Int
init n = A {cameFrom = Nothing, lastVal = n, visited = []}
To change values: strictly speaking you don't change values, you return another different value, like this:
toGetBackTo :: Direction -> Memory a -> Memory a
toGetBackTo dir memory = memory {cameFrom = Just dir, visited = dir : visited memory}

How to declare function (type misunderstanding Maybe)

I need a function which works like:
some :: (Int, Maybe Int) -> Int
some a b
| b == Nothing = 0
| otherwise = a + b
Use cases:
some (2,Just 1)
some (3,Nothing)
map some [(2, Just 1), (3,Nothing)]
But my code raise the error:
The equation(s) for `some' have two arguments,
but its type `(Int, Maybe Int) -> Int' has only one
I don't understand it.
Thanks in advance.
When you write
foo x y = ...
That is notation for a curried function, with a type like:
foo :: a -> b -> c
You have declared your function to expect a tuple, so you must write it:
some :: (Int, Maybe Int) -> Int
some (x, y) = ...
But Haskell convention is usually to take arguments in the former curried form. Seeing funcitons take tuples as arguments is very rare.
For the other part of your question, you probably want to express it with pattern matching. You could say:
foo :: Maybe Int -> Int
foo Nothing = 0
foo (Just x) = x + 1
Generalizing that to the OP's question is left as an exercise for the reader.
Your error doesn't come from a misunderstanding of Maybe: The type signature of some indicates that it takes a pair (Int, Maybe Int), while in your definition you provide it two arguments. The definition should thus begin with some (a,b) to match the type signature.
One way to fix the problem (which is also a bit more idiomatic and uses pattern matching) is:
some :: (Int, Maybe Int) -> Int
some (a, Nothing) = a
some (a, Just b) = a + b
It's also worth noting that unless you have a really good reason for using a tuple as input, you should probably not do so. If your signature were instead some :: Int -> Maybe Int -> Int, you'd have a function of two arguments, which can be curried. Then you'd write something like
some :: Int -> Maybe Int -> Int
some a Nothing = a
some a (Just b) = a + b
Also, you might want to add the following immediate generalization: All Num types are additive, so you might aswell do
some :: (Num n) => n -> Maybe n -> n
some a Nothing = a
some a (Just b) = a + b
(I've violated the common practice of using a, b, c... for type variables so as not to confuse the OP since he binds a and b to the arguments of some).

Resources