Why does Haskell's Monad implementation fail function result differ from error's result? - haskell

I am trying to understand monads and reading it's type class definition:
class Monad m where
.
.
.
fail :: String -> m a
fail msg = error msg
Now, the definition of error is:
error :: [Char] -> a
Shouldn't the type system complain in this case? as
a /= m a
Or does the type system automatically assume that the results from error will be transformed into
m a
somehow?
Thanks in advance

The as in fail's and error's type signatures are a type variables. We can rename them without changing their meaning, e.g.
error :: [Char] -> b
error :: [Char] -> c
error :: [Char] -> d
All those type signatures have the same meaning; we just used alpha conversion on the type level.
Now we set b ~ m a, where m is fixed by fail's context and we see that error can get used:
fail :: String -> m a
fail msg = error msg -- error :: String -> b
-- b ~ m a

Related

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

Non type-variable argument for MonadWriter

I just tried to use writer:
writer (5, "Hello, World")
But I noticed I get an error:
Non type-variable argument in the constraint MonadWriter [Char] m
But I wonder what constraint I don't fulfill? [a] after all is a Monoid...
It’s just a check to keep type checking “simple”
writer (5, "Hello world") :: (MonadWriter String m, Num n) => m n
which is a perfectly sensible type. However, by default, it is not allowed, because the constraint MonadWriter String m contains a type argument String, which isn’t a variable. This was done with the intent that it would stop the delaying of type errors:
class C c where c :: c -> c
-- no instance C Int
x :: C Int => Int
x = c (5 :: Int)
-- illegal with above restriction
-- missing instance error (maybe) delayed to user without
Simply set -XFlexibleContexts to disable the check.
As for other monads, I’m pretty sure Reader, State, and Free will do this too.

Couldn't match type `h' with `String'

I'm starting in Haskell and I would like your help and intuition on why the following code does not work. The main idea is to do a class that represents Probability mass functions
--a encapsulates a set of hypotheses of type h
class Pmf a where
hypos :: a -> [h]
prob :: a -> h -> Double
probList :: a -> [(h,Double)]
probList a = map (\h->(h, prob a h)) $ hypos a
The idea is for it to be general, so for instance I could define
data BoxSet = BoxSet { ids::[String], items::[(String,Int)]} deriving(Show)
and make BoxSet an instance like
instance Pmf BoxSet where
hypos = ids
prob cj _ = let one = 1
len = doubleLength $ ids cj in one/len
but this gives the following error
<interactive>:2:13: error:
* Couldn't match type `h' with `String'
`h' is a rigid type variable bound by
the type signature for:
hypos :: forall h. BoxSet -> [h]
at <interactive>:2:5
Expected type: BoxSet -> [h]
Actual type: BoxSet -> [String]
* In the expression: ids
In an equation for `hypos': hypos = ids
In the instance declaration for `Pmf BoxSet'
* Relevant bindings include hypos :: BoxSet -> [h] (bound at <interactive>:2:5)
Its possible to put h as additional class parameter but then in the future I will expand the class with a new type d for data and i will have this problem
So then, I would appreciate if you could tell me why String can not be matched as h and how could this be solved. I understand that it expects any h with any type but in an instance it makes sense to give h a specific type.
Also, I think I might not be on the functional mindset fully here. So if you can point a better way to model these Pmf I would gladly try it!.
This
class Pmf a where
hypos :: a -> [h]
prob :: a -> h -> Double
is short for
class Pmf a where
hypos :: forall h. a -> [h]
prob :: forall h. a -> h -> Double
That is, the hs in the two signatures are unrelated, and furthermore each of these functions needs to work for any h that the caller might choose. I think you are looking for either type families
class Pmf a where
type Hypothesis a :: *
hypos :: a -> [Hypothesis a]
...
instance Pmf BoxSet where
type Hypothesis BoxSet = String
...
or functional dependencies, which do the same kind of thing but with a different swagger
class Pmf a h | a -> h where
hypos :: a -> [h]
...
instance Pmf BoxSet String where
...
There are a handful of extensions needed for each, I think the error messages will lead the way.

Basic Haskell function types?

Super basic question - but I can't seem to get a clear answer. The below function won't compile:
randomfunc :: a -> a -> b
randomfunc e1 e2
| e1 > 2 && e2 > 2 = "Both greater"
| otherwise = "Not both greater"
main = do
let x = randomfunc 2 1
putStrLn $ show x
I'm confused as to why this won't work. Both parameters are type 'a' (Ints) and the return parameter is type 'b' (String)?
Error:
"Couldn't match expected type ‘b’ with actual type ‘[Char]’"
Not quite. Your function signature indicates: for all types a and b, randomfunc will return something of type b if given two things of type a.
However, randomFunc returns a String ([Char]). And since you compare e1 with 2 each other, you cannot use all a's, only those that can be used with >:
(>) :: Ord a => a -> a -> Bool
Note that e1 > 2 also needs a way to create such an an a from 2:
(> 2) :: (Num a, Ord a) => a -> Bool
So either use a specific type, or make sure that you handle all those constraints correctly:
randomfunc :: Int -> Int -> String
randomFunc :: (Ord a, Num a) => a -> a -> String
Both parameters are type 'a' (Ints) and the return parameter is type 'b' (String)?
In a Haskell type signature, when you write names that begin with a lowercase letter such as a, the compiler implicitly adds forall a. to the beginning of the type. So, this is what the compiler actually sees:
randomfunc :: forall a b. a -> a -> b
The type signature claims that your function will work for whatever ("for all") types a and b the caller throws at you. But this is not true for your function, since it only works on Int and String respectively.
You need to make your type more specific:
randomfunc :: Int -> Int -> String
On the other hand, perhaps you intended to ask the compiler to fill out a and b for you automatically, rather than to claim that it will work for all a and b. In that case, what you are really looking for is the PartialTypeSignatures feature:
{-# LANGUAGE PartialTypeSignatures #-}
randomfunc :: _a -> _a -> _b

Haskell confusion with ContT, callCC, when

Continuing quest to make sense of ContT and friends. Please consider the (absurd but illustrative) code below:
v :: IO (Either String [String])
v = return $ Left "Error message"
doit :: IO (Either String ())
doit = (flip runContT return) $ callCC $ \k -> do
x <- liftIO $ v
x2 <- either (k . Left) return x
when True $ k (Left "Error message 2")
-- k (Left "Error message 3")
return $ Right () -- success
This code does not compile. However, if the replace the when with the commented k call below it, it compiles. What's going on?
Alternatively, if I comment out the x2 line, it also compiles. ???
Obviously, this is a distilled version of the original code and so all of the elements serve a purpose. Appreciate explanatory help on what's going on and how to fix it. Thanks.
The problem here has to do with the types of when and either, not anything particular to ContT:
when :: forall (m :: * -> *). (Monad m) => Bool -> m () -> m ()
either :: forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
The second argument needs to be of type m () for some monad m. The when line of your code could thus be amended like so:
when True $ k (Left "Error message 2") >> return ()
to make the code compile. This is probably not what you want to do, but it gives us a hint as to what might be wrong: k's type has been inferred to be something unpalatable to when.
Now for the either signature: notice that the two arguments to either must be functions which produce results of the same type. The type of return here is determined by the type of x, which is in turn fixed by the explicit signature on v. Thus the (k . Left) bit must have the same type; this in turn fixes the type of k at (GHC-determined)
k :: Either String () -> ContT (Either String ()) IO [String]
This is incompatible with when's expectations.
When you comment out the x2 line, however, its effect on the type checker's view of the code is removed, so k is no longer forced into an inconvenient type and is free to assume the type
k :: Either [Char] () -> ContT (Either [Char] ()) IO ()
which is fine in when's book. Thus, the code compiles.
As a final note, I used GHCi's breakpoints facility to obtain the exact types of k under the two scenarios -- I'm nowhere near expert enough to write them out by hand and be in any way assured of their correctness. :-) Use :break ModuleName line-number column-number to try it out.

Resources