Data initialization and data members change in Haskell - 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}

Related

Return value for type in Haskell

I haven't find anything similar in stackoverflow. I am doing some university stuff, but got stuck with the following.
So I have two types.
type Val = Either Int Bool
type Env = [(Name, Val)]
One of them is understandable. So Env is a list of tupples where the first value of the tupple is a type Name = String
But what is up with the type called Val? Like how do I return a value for it?
I have a snippet for something what I would do. But says type error.
Any tips?
evalExp :: Exp -> (Env -> Val)
evalExp exp env = go exp where
go :: Exp -> Val
go (IntLit n) = n
An Either a b has two data constructors: a Left a, and a Right b.
In this case we use Either Int Bool, so we can construct an object with Left someInt and Right someBool.
Likly the n in IntLit is an Int, so we can return a :
go :: Exp -> Val
go (IntLit n) = Left n
data Either a b = Left a | Right b
so type Val = Either Int Bool is for either Int or Bool
your go would be
go :: Exp -> Val
go (IntLit n) = Left n
go ...

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

Haskell do-block return error

I have a simple function:
func :: Int
func = do
x <- 1
return x
But I got an error message as follows:
Couldn't match type ‘m0 b0’ with ‘Int’
What's wrong with my function?
There are two problems with your code:
The right side of <- must have the type m a where a is an arbitrary type (that then becomes the type of the left side) and m is the monad that the do-block belongs to. In your case the type of the right side is 1, which does not have that type.
If all you want to do is to bind a value to x, you need to use let x = 1, not <-.
The type of return is Monad m => a -> m a, so if we take the type of x to be Int, the type of return x is Monad m => m Int. But according to your type signature, you just want the type to be Int, not m Int. Therefore you shouldn't use return (or do-notation for that matter).
The correct way to write the definition that you're trying to write would be:
f = 1
or if you want to have a local x
f =
let x = 1 in
x
or
f = x
where x = 1

Different setter and getter types in Haskell's lenses

I've got a data type G, which have got field _repr :: Data.Graph.Inductive.Gr String String. The normal way, when adding new node into Gr graph, we have to provide an LNode a object, which basically is defined as a tuple of (Int, a), where Int is the nodes index in Graph - see the example function add below.
I want to implement a function addx, which will compute the index automatically (for example by using Data.Graph.Inductive.newNodes function). I want the addx to have signature of addx :: String -> G -> Int and this function will compute new free index, modify the graph G and return this computed index. Is it possible in Haskell to create such function (which will modify an existing object - G in this case) - by using lenses or something like that?
I have seen, that Haskell lens is defined like lens :: (a -> c) -> (a -> d -> b) -> Lens a b c d and lens is basically a "getter" and "setter", so its signature allows for different types of getter output (c), setter value (d) and setter output (b).
import qualified Data.Graph.Inductive as DG
data G = G { _repr :: DG.Gr String String, _name::String} deriving ( Show )
empty :: G
empty = G DG.empty ""
add :: DG.LNode String -> G -> G
add node g = g{_repr = DG.insNode node $ _repr g}
-- is it possible to define it?
addx :: String -> G -> Int
addx name g = undefined
main :: IO ()
main = do
let g = add (1, "test2")
$ add (0, "test1")
$ empty
n1 = addx "test2" g
g2 = DG.insEdge(n1,0)
$ DG.insEdge(0,1)
print $ g
Your type for addx is broken since you can't modify G in a pure function without returning the modified form like addx1 :: String -> G -> (Int, G). If you have a clever eye for Haskell monads, you might notice that this has an isomorphic type, addx2 :: String -> State G Int.
We can align everything to this "stateful" orientation
add' node = do g <- get
put $ g { _repr = DB.insNode node $ _repr g }
and make it more succinct with lenses
add'' node = repr %= DB.insNode node
The real challenge here is, at the end of the day, tracking the node identity. One way would be to carry it alongside the repr in your type
data G = G { _repr :: DG.Gr String String, _name :: String, _index :: Int }
empty = G DG.empty "" 0
then use that when building nodes (using lenses again!)
addx' name = do i <- use index
repr %= DB.insNode (i, node)
i += 1

The Type signature lacks an appropriate binding [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

Resources