Accessing a list entry and showing its values - haskell

I have a function
(.#.) :: [a] -> Integer -> a -- 1-indexing with 'Integer'
xs .#. j = xs !! (fromIntegral $ j-1)
showIntegers :: [Integer] -> String
showIntegers r = let
str = concat $ "List: " : [r (.#.) j | j <- [1..length r]]
How can I show r (.#.) j as a Char/String rather than an integer? I tried using show, but it gave me an error.
Here is an example of how I used show:
str = concat $ "List: " : [show $ r (.#.) j | j <- [1..length r]]
Example input and output:
> showIntegers [1,2,3]
List: 1 2 3

You should just use Data.List.intercalate or even better use unwords.
import Data.List
showIntegers :: [Integer] -> String
showIntegers r = "List: " ++ intercalate " " $ map show r
--showIntegers r = "List: " ++ unwords $ map show r
EDIT: In either case you should avoid using !! especially to enumerate the original list.
First I would get rid of .#. it is just going to confuse you to use a different numbering system, best to rip that bandaid off.
Next realize that [show $ r !! j <- 0 .. length r - 1] is the same as map show r (and the latter is standard).
Now going with that you have: concat $ "List: " : (map show r) which creates List: 123 because we lost the spaces.
We could reproduce the spaces but what is the difference between using intercalate and concat? Honestly the best solution without using intercalate would be to reproduce intercalate (whose source code is available on Hackage).

Just remove the parenthesis around (.#.) and it works.
If you have an infix operator !#$ , with something before and after it, e.g. x !#$ y, you must not use parentheses. In the other cases, add parentheses, like in the type declaration.
(this technically answers the question, but Guvante's advice is better.)

Related

Haskell: how can I take each number from a list separately?

I'm trying to duplicate a "-" character for 0 to n number of times, add a '*' and add a duplicate of "-" character again for n to 0 times recursively, e.g.:
If n = 5, I'd like the answer to be:
*-----
-*----
--*---
---*--
----*-
-----*
duplicate :: String -> Int -> String -- will be used to duplicate spaces
duplicate string n =
concat $ replicate n string
block :: Int -> String
block n =
duplicate ***from 0 to n*** "-" ++ '*' ++ duplicate ***from n to 0*** "-"
How can I do this?
The simplest way is to create a function that prints one line:
line width idx = duplicate "-" idx ++ "*" ++ duplicate "-" (width - idx - 1) ++ "\n"
And then map it over a list [0..(n-1)], then concatenate results:
block n = concat $ map (line n) [0..(n-1)]
Or, for a more intuitively looking solution, you can do the same thing as a list comprehension:
block n = concat
[ duplicate "-" i ++ "*" ++ duplicate "-" (n - i - 1) ++ "\n"
| i <- [0..(n-1)]
]
A simple code to handle this job could be;
\n -> (drop <> take) <$> [n+1,n..1] <*> ['*':replicate n '-']
I had explained about drop <> take :: Int -> [a] -> [a] in a previous answer of mine. fmap (<$>) and applicative op (<*>) should be clear.

Variable not in scope error in function using guards

I am trying to print a linked list in Haskell using the following code:
data List = Node {value:: Double, next:: List}
| Empty
printList :: List -> String
printList x | x == (Node v n) = show v ++ " " ++ printList n
| otherwise = show '_'
And getting the compilation error:
:load scratch.hs
[1 of 1] Compiling Main ( scratch.hs, interpreted )
scratch.hs:5:26: error: Variable not in scope: v :: Double
scratch.hs:5:28: error: Variable not in scope: n :: List
scratch.hs:5:38: error: Variable not in scope: v
scratch.hs:5:53: error: Variable not in scope: n :: List
Failed, modules loaded: none.
While I'm able to do the same using pattern matching without guards.
printList (Node v n) = show v ++ " " ++ printList n
printList Empty = ""
What's wrong with the first code?
You do not do pattern matching by using an equality check: it is possible that two different patterns are considered equal.
So what you can do is define a pattern in the head of one of the clauses of your function. For instance:
printList :: List -> String
printList (Node v n) = show v ++ " " ++ printList n
printList _ = show '_'
So now Haskell will, for a given List check if it matches with the Node v n pattern, and if so unpack the element and assign the head to v and the tail to n.
We can however still improve the code. Usually you better do not use wildcard patterns, but use all possible patterns. Since if you later want to alter the definition of List, the compiler can give you a warning that you forgot a pattern:
printList :: List -> String
printList (Node v n) = show v ++ " " ++ printList n
printList Empty = show '_'
Another thing we can improve is using "_" over show '_'. Since show '_' will add quotes to the content. For instance:
printList :: List -> String
printList (Node v n) = show v ++ " " ++ printList n
printList Empty = "_"
Finally we can also use a "cons" construction over appending with a singleton list:
printList :: List -> String
printList (Node v n) = show v ++ ' ' : printList n
printList Empty = "_"

How to add spaces to string in Haskell

I have a string "AB0123456789" and the output I would like to have is: "AB01 2345 6789" ... I want to add a space after every fourth character. How can I do this?
Main> addSpace "AB0123456789"
"AB01 2345 6789"
With Data.List.intercalate and Data.List.Split.chunksOf this is easy:
import Data.List.Split
addSpace :: String -> String
addSpace = intercalate " " . chunksOf 4
This may not be the most efficient:
addSpace xs = if length xs <= 4
then xs
else take 4 xs ++ " " ++ addSpace (drop 4 xs)
Demo in ghci:
ghci > addSpace "AB0123456789"
"AB01 2345 6789"
I would think pattern matching would make this easiest:
addSpaces :: String -> String
addSpaces xs#(_:_:_:_:[]) = xs
addSpaces (a:b:c:d:xs) = a:b:c:d:' ':addSpaces xs
addSpaces xs = xs
You have to include the first case so you don't potentially get a space at the end, but it's pretty straightforward. This isn't extensible, though, you wouldn't be able to use a function like this to dynamically choose how many characters you want to skip before inserting a space (such as in #cdk's answer)
You can use splitAt. Heres a function that adds space after every nth character.
spaceN :: Int -> String -> String
spaceN n = init . go
where go [] = []
go xs = let (as, bs) = splitAt n xs in as ++ (' ' : go bs)
for your specific case:
λ. spaceN 4 "AB0123456789"
"AB01 2345 6789"
window :: Int -> [a] -> [[a]]
window i = unfoldr (\l -> if null l then Nothing else Just (splitAt i l))
addSpace :: String -> String
addSpace = intercalate " " . window 4

Haskell - how to generate permutations

How can I create a function which lazily makes permutations for the chars '_' and '*' like this:
For example:
Main> function 3
["___","*__","_*_","__*","**_","_**","*_*","***"]
First element is made only from _, the next 3 are permutations that lists: *__, the second 3 are permutations that lists **_, and the last element contains only *.
How can I do that?
Here's another "correct order" version:
function :: Int -> [String]
function c = concatMap helper $ zip (reverse [0..c]) [0..c]
helper :: (Int, Int) -> [String]
helper (c, 0) = [replicate c '_']
helper (0, c) = [replicate c '*']
helper (cUnderscores, cAsterisks) = map ('_' :) (helper (cUnderscores - 1, cAsterisks))
++ map ('*' :) (helper (cUnderscores, cAsterisks - 1))
You might want to look at replicateM.
let k = ["_", "*"]
let p = [ a ++ b ++ c | a <- k, b <- k, c <- k ]
The “correct order” version:
import Data.List
function k = concatMap (nub . permutations . pat) [0..k]
where pat x = replicate x '*' ++ replicate (k-x) '_'
I don’t know how to step from one permutation to another in constant time, though.

Haskell string list through lines

I'm using the lines functionality to take an input and split up many variables before sending it off to a function. Please look at the run function and tell me why I get the following error. It seems like it should just assign the first string in ln to seq, but I get an error.
ERROR:dishonest.hs:33:11:
Couldn't match expected type `[t]' against inferred type `Char'
In a 'do' expression: seq <- ln !! 0
In the expression:
do ln <- lines s
seq <- ln !! 0
states <- ln !! 1
l1 <- listDouble (ln !! 2)
....
In the definition of `run':
run s = do ln <- lines s
seq <- ln !! 0
states <- ln !! 1
....
code follows...
import Char
maximumInd :: (Double, Double) -> Int
maximumInd (d1,d2) | maximum [d1,d2] == d1 = 1
| maximum [d1,d2] == d2 = 2
scoreFunction :: String -> Int -> [Double] -> [Double] -> Double -> Double -> (Double,Double)
scoreFunction string (-1) l1 l2 t1 t2 = (0.5, 0.5)
scoreFunction string index l1 l2 t1 t2 = ((fst (scoreFunction string (index-1) l1 l2 t1 t2)) * (l1!!num) * (tr (maximumInd (scoreFunction string (index-1) l1 l2 t1 t2))!!1), (snd (scoreFunction string (index-1) l1 l2 t1 t2)) * (l2!!num) * (tr (maximumInd (scoreFunction string (index-1) l1 l2 t1 t2))!!2))
where
num = digitToInt (string!!index)
tr n | n == 1 = l1
| n == 2 = l2
--split is stolen from teh webs http://julipedia.blogspot.com/2006/08/split-function-in-haskell.html
split :: String -> Char -> [String]
split [] delim = [""]
split (c:cs) delim
| c == delim = "" : rest
| otherwise = (c : head rest) : tail rest
where
rest = split cs delim
readDouble :: String -> Double
readDouble s = read s :: Double
listDouble :: String -> [Double]
listDouble s = map readDouble $ split s ' '
run :: String -> String
run s = do
ln <- lines s
seq <- ln!!0
states <- ln!!1
l1 <- listDouble (ln!!2)
l2 <- listDouble (ln!!3)
tr1 <- readDouble (ln!!4)
tr2 <- readDouble (ln!!5)
show maximumInd (scoreFunction seq (length seq) l1 l2 tr1 tr2)
main = do
putStrLn "Please compose a test job for Viterbi."
putStrLn "First line: A sequence with language [1,9]."
putStrLn "Second line: The number of states."
putStrLn "For the next 2 lines: space delimited emission probabilities."
putStrLn "For the 2 lines after that, transmission probabilities."
putStrLn "Then do ./casino < filename "
interact run
First, let's look at how the compiler is interpreting it:
run :: String -> String
String is in fact [Char].
run s = do
ln <- lines s
...
Simplifying things a lot, a do block must "run" in a Monad. This means that it "returns" a value of type (Monad t) => t a. Since this function is returning [Char], the do block will return [Char], meaning the Monad is [] (if you read [a] as [] a, it will be more clear).
Copying from another answer of mine,
Simplifying things a lot, on a do block on the IO monad, every line is either:
Something which returns a value of the "IO a" type; the value of the "a" type within it is discarded (so the "a" is often "()")
A <- expression, which does the same thing but instead of discarding the value of the "a" type gives it the name to the left of the <-
A let, which does nothing more than give a name to a value
Here we are not on the IO Monad, but on the [] Monad. So the expression to the right of the <- must be a [a].
So, in the first line of the do block:
ln <- lines s
Here the type is [[Char]], and so the type of ln is [Char].
On the next line:
seq <- ln!!0
Here ln!!0 has type Char, but since you are in the [] Monad, it is expecting a list of some sort. This is what causes the compiler's error message.
The solution is to, instead of using the do notation, use a plain let block:
run :: String -> String
run s = let
ln = lines s
seq = ln!!0
states = ln!!1
l1 = listDouble (ln!!2)
l2 = listDouble (ln!!3)
tr1 = readDouble (ln!!4)
tr2 = readDouble (ln!!5)
in show maximumInd (scoreFunction seq (length seq) l1 l2 tr1 tr2)
I did not compile this block, but even if there is something else wrong with it, it should be enough to get you going again.
I'm not sure if this is right, but the issue might lay in the fact that <- isn't an assignment operator, as you seem to be using it; it essentially unpacks a value from a monad. But I'm not really sure if that's the cause of your issue or not.
Yeah i think mipadi is right. the do notation translates into >>= and return calls to the list monad.
run s = do
ln <- lines s
seq <- ln!!0
states <- ln!!1
Will get the list that is returned by lines s and for the seq and states, ln will be a string of that list each time. So actually with ln!!0, you get the first character of that string. But a list is required at the right side of the <- there. That's just about all what i remember. Has been quite a bit of time since i did those stuff with haskell :)
Remember that lists are monads in haskell, with the definition:
instance Monad [] where
m >>= f = concatMap f m
return x = [x]
fail s = []
So if you take your code, which goes something like:
do {ln <- lines "hello, world"; ln!!0}
That is equivalent to the following using bind notation:
lines "hello world" >>= (\ln -> ln!!0)
or more concisely:
lines "hello world" >>= (!!0)
We can now use the definition of the list monad to re-write that as the following:
concatMap (!!0) (lines "hello, world")
Which is equivalent to:
concat $ map (!!0) (lines "hello, world")
lines "hello, world" will return ["hello, world"], so mapping (!!0) over it will produce the string "h". That has type [Char], but concat requires a type [[t]]. Char does not match [t], hence the error.
Try using a let or something rather than do notation.
Edit:
So I think this is what you want, using let rather than do.
run :: String -> String
run s = let ln = lines s
seq = ln!!0
states = ln!!1
l1 = listDouble (ln!!2)
l2 = listDouble (ln!!3)
tr1 = readDouble (ln!!4)
tr2 = readDouble (ln!!5)
in show $ maximumInd (scoreFunction seq (length seq) l1 l2 tr1 tr2)
run is of type String -> String, so you probably don't want the do notation[1]. I'd advise you to do this:
comment out everything below the
listDouble function, load that, and
be sure that'll compile.
add a test value that's formatted like the file you expect. Something like:
t = "[1,9]\n3\n1.0 1.0 1.0\n1.0 1.0 1.0\n1.0\n1.0"
add a test values that the top level for the values you're defining in run
ln = lines t
seq = ln!!0
states = ln!!1
l1 = listDouble (ln!!2)
l2 = listDouble (ln!!3)
tr1 = readDouble (ln!!4)
tr2 = readDouble (ln!!5)
use the type signature of
scoreFunction to guide you in
building the arguments to that
function, then the rest of run, and finally main.
Learn to use an interpreter, such as Hugs, ghci. Learn the :r and :t commands. For example (i'm using currying to give some but not all of a functions arguments):
:t scoreFunction
:t scoreFunction ""
:t scoreFunction 3445
You can use this to have the system help you determine if you're on the right track.
Doing this at the top level with introduce a conflict with a Prelude.seq function - either rename your seq, or refernence yours as Main.seq.
Haskell is notorious for error messages that are inscrutable to beginners, so I'd recommend periodically rolling back to a version that compiles, either by commenting out your current experiments (which is what I had you do in step 1 above), or using your editors undo function.
[1]I say probably because Strings, being lists of Characters, are instances of the Monad class, but that's fairly advanced

Resources