searching in sorted Indexes of tuple list by bubble sort in haskell - haskell

I choice binary search for index of array of record ascasestudy for my graduate research by c++ and haskell I write the c++ code and work and now I work for the haskell one
import Data.List
data BookInfo = Book Int String [String]
deriving (Show)
--Entering the variables
entering :: Int String [String]-> Book
entering id name subject= Book id name subject
--make an idex of the array of tuples
index :: [Book]->[Int]
index [m] = getID (Book id _ _ ) = id
main :: IO ()
main = do
putStrLn "Please enter your book id,name,Subject"
Book inpStr <- getLine
putStrLn print r
-- BubbleSort using map
bubbleSort ::(Ord x) => [x] -> [x]
bubbleSort (x':xs) = if x>x' then x': bubbleSort(x:xs)
else
if x<x' then x: bubbleSort(x':xs)
else
x: bubbleSort(X':xs)
bubble ::[a] -> [a]
bubble [a] = map bubbleSort [a]
--Make index for the array
indexsort(ord a)::[int]->[Int]
indexsort a=bubble a
--Make the list of tuples
addBooks2List Book->[Book]->[Book]
addBooks2List b m=b:entering b':m
--binarysearch
binarysearch [Int]->Int->Int->Int->Int
a=bubble x
binaryseach a i m j=
let u=(i+m)/2
if a[u]=j then u
if a[u]>j then binaryseach a i u-1 j
else
if a[u]<j then binarysearch a u+1 m j
if i=m "Not found"
--printing the tuple that has the searched id
print::Int->Book
print r= Book r y z
r=binaryseach m 0 (length m)
it made an error at 8:3 parse error on input 'entering' what this error mean? and how I can correct it ?

For one thing, the type signature for entering should read
entering :: Int -> String -> [String] -> BookInfo
rather than entering :: Int String [String]-> Book—but that's a type error, not a parse error.
Perhaps your indentation is wrong, but that's hard to tell without having your code available verbatim. Remember: in Haskell, as opposed to languages such as C and Java, the layout of your code matters.
Anyway, the code, as you have posted it, is far from a working solution for your problem. You may want to take a few steps back and study how to write elementary functions in Haskell and then, later, how to glue them together in order to get at more involved programs. I really doubt whether learning the language by trying to convert snippets of C++ into Haskell has a high chance of success. Just my two cents, though...

There are so many problems in your code, you best start with a single function and grow your program slowly and see that you get the incremental pieces compiled. Starting with this:
entering :: Int String [String]-> Book
entering id name subject= Book id name subject
First, Book is not a type but a data constructor, the type is BookInfo. Then, you're missing the arrows (as dblhelix pointed out). So it should read:
entering :: Int -> String -> [String]-> BookInfo
entering id name subject= Book id name subject
This will compile. However, entering now is just the same as Book. Anyway, continue with adding the next function and getting it compiled and so on.
If we go on,
index :: [Book]->[Int]
index [m] =
The definition is missing (what's on the right-hand side of =?), and [m] will only match a lists with a single element which is probably not what you want. Complete this function, or comment it out and continue with the rest. Apparently you don't use it at all currently. And so on.

Related

Trouble with the State Monad

I am trying to write a program to generate 'word chains', e.g. bat -> cat -> cot -> bot, using the list monad (mostly comprehensions) to generate combinations of words, and the state monad to build up the actual chain as i go through the possibilities. That second part is giving me trouble:
import Control.Monad.State
type Word = String
type Chain = [Word]
getNext :: Word -> State Chain Word
getNext word = do
list <- get
return (list ++ "current word")
The part where I generate words works and is given below, but as you can see I don't really know what I'm doing in this part. Basically wordVariations :: Word -> [Word] takes a Word and returns a list of Words that differ in one letter from the given word. I'm trying to change this so that each word has a state signifying its predecessors:
For example: input = "cat". the final value is "got", the final state is ["cat","cot","got"]
What I have now will give me "got" from "cat" after 3 steps, but won't tell me how it got there.
None of the State Monad tutorials I found online were terribly helpful. The above code, when compiled with GHC, gives the error:
WordChain.hs:42:11:
Couldn't match type `Word' with `Char'
When using functional dependencies to combine
MonadState s (StateT s m),
arising from the dependency `m -> s'
in the instance declaration in `Control.Monad.State.Class'
MonadState [Char] (StateT Chain Data.Functor.Identity.Identity),
arising from a use of `get' at WordChain.hs:42:11-13
In a stmt of a 'do' block: list <- get
In the expression:
do { list <- get;
return (list ++ "current word") }
Failed, modules loaded: none.
This is just meant to be a test to work off of, but I can't figure it out!
The code in full is below in case it is helpful. I know this may not be the smartest way to do this, but it is a good opportunity to learn about the state monad. I am open to necessary changes in the way the code works also, because I suspect that some major refactoring will be called for:
import Control.Monad.State
type Word = String
type Dict = [String]
-- data Chain = Chain [Word] deriving (Show)
replaceAtIndex :: Int -> a -> [a] -> [a]
replaceAtIndex n item ls = a ++ (item:b) where (a, (_:b)) = splitAt n ls
tryLetter str c = [replaceAtIndex n c str | n <- [0..(length str - 1)]]
wordVariations str = tryLetter str =<< ['a' .. 'z']
testDict :: Dict
testDict = ["cat","cog","cot","dog"]
------- implement state to record chain
type Chain = [Word] -- [cat,cot,got,tot], etc. state var.
startingState = [""] :: Chain
getNext :: Word -> State Chain Word
getNext w = do
list <- get
return ( list ++ "current word")
First of all, the error you posted is in this line return ( list ++ "current word").
"current word" type is Word, which is an alias for String, which is an alias for[Char]`.
The variable list has a type of Chain, which is an alias for [Word], which is an alias for [[Char]].
The type signature of the function forces the return type must be a Word.
++ requires that the types on both sides be a list with the same type, (++) :: [a] -> [a] -> [a].
However, if you plug in the above type signatures, you get the type [Word] -> [Char] -> [Char] which has mismatched "a"s.
Quick but fairly important performance side note: prepending to a list is much faster then appending, so you might want to consider building them backwards and using (:) and reversing them at the end.
The State Monad is not really the right choice for storing the steps used to get to the result. At least it is certainly overkill, when the List Monad would be sufficient to complete the task. Consider:
-- given a list of words, find all possible subsequent lists of words
getNext :: [String] -> [[String]]
getNext words#(newest:_) = fmap (:words) (wordVariations newest)
-- lazily construct all chains of every length for every word
wordChains :: String -> [[[String]]]
wordChains word = chain
where chain = [[word]] : map (>>= getNext) chain
-- all the 5 word long chains starting with the word "bat"
batchains = wordChains "bat" !! 4
(Disclaimer: code compiled, but not run).
getNext takes a Chain, and returns a list containing a list of Chains, where each one has a different prepended successor in the chain. Since they share a common tail, this is memory efficient.
In wordChains, by repeatedly mapping using the list monad with (>>= getNext), you end up with a lazy infinite list, where the zeroth item is a Chain the starting word, the first item is all 2 item Chains where the first is the starting word, the second item is all 3 item chains, and so on. If you just want one chain of length 5, you can grab the head of the 4th item, and it will do just enough computation to create that for you, but you can also get all of them.
Also, getNext could be expanded to not repeat words by filtering.
Finally, when it comes to finding wordVariations, another algorithm would be to construct a filter which returns True if the lengths of two words are the same and the number of characters that are different between them is exactly 1. Then you could filter over a dictionary, instead of trying every possible letter variation.
Good luck!

Why am I receiving this syntax error - possibly due to bad layout?

I've just started trying to learn haskell and functional programming. I'm trying to write this function that will convert a binary string into its decimal equivalent. Please could someone point out why I am constantly getting the error:
"BinToDecimal.hs":19 - Syntax error in expression (unexpected `}', possibly due to bad layout)
module BinToDecimal where
total :: [Integer]
total = []
binToDecimal :: String -> Integer
binToDecimal a = if (null a) then (sum total)
else if (head a == "0") then binToDecimal (tail a)
else if (head a == "1") then total ++ (2^((length a)-1))
binToDecimal (tail a)
So, total may not be doing what you think it is. total isn't a mutable variable that you're changing, it will always be the empty list []. I think your function should include another parameter for the list you're building up. I would implement this by having binToDecimal call a helper function with the starting case of an empty list, like so:
binToDecimal :: String -> Integer
binToDecimal s = binToDecimal' s []
binToDecimal' :: String -> [Integer] -> Integer
-- implement binToDecimal' here
In addition to what #Sibi has said, I would highly recommend using pattern matching rather than nested if-else. For example, I'd implement the base case of binToDecimal' like so:
binToDecimal' :: String -> [Integer] -> Integer
binToDecimal' "" total = sum total -- when the first argument is the empty string, just sum total. Equivalent to `if (null a) then (sum total)`
-- Include other pattern matching statements here to handle your other if/else cases
If you think it'd be helpful, I can provide the full implementation of this function instead of giving tips.
Ok, let me give you hints to get you started:
You cannot do head a == "0" because "0" is String. Since the type of a is [Char], the type of head a is Char and you have to compare it with an Char. You can solve it using head a == '0'. Note that "0" and '0' are different.
Similarly, rectify your type error in head a == "1"
This won't typecheck: total ++ (2^((length a)-1)) because the type of total is [Integer] and the type of (2^((length a)-1)) is Integer. For the function ++ to typecheck both arguments passed to it should be list of the same type.
You are possible missing an else block at last. (before the code binToDecimal (tail a))
That being said, instead of using nested if else expression, try to use guards as they will increase the readability greatly.
There are many things we can improve here (but no worries, this is perfectly normal in the beginning, there is so much to learn when we start Haskell!!!).
First of all, a string is definitely not an appropriate way to represent a binary, because nothing prevents us to write "éaldkgjasdg" in place of a proper binary. So, the first thing is to define our binary type:
data Binary = Zero | One deriving (Show)
We just say that it can be Zero or One. The deriving (Show) will allow us to have the result displayed when run in GHCI.
In Haskell to solve problem we tend to start with a more general case to dive then in our particular case. The thing we need here is a function with an additional argument which holds the total. Note the use of pattern matching instead of ifs which makes the function easier to read.
binToDecimalAcc :: [Binary] -> Integer -> Integer
binToDecimalAcc [] acc = acc
binToDecimalAcc (Zero:xs) acc = binToDecimalAcc xs acc
binToDecimalAcc (One:xs) acc = binToDecimalAcc xs $ acc + 2^(length xs)
Finally, since we want only to have to pass a single parameter we define or specific function where the acc value is 0:
binToDecimal :: [Binary] -> Integer
binToDecimal binaries = binToDecimalAcc binaries 0
We can run a test in GHCI:
test1 = binToDecimal [One, Zero, One, Zero, One, Zero]
> 42
OK, all fine, but what if you really need to convert a string to a decimal? Then, we need a function able to convert this string to a binary. The problem as seen above is that not all strings are proper binaries. To handle this, we will need to report some sort of error. The solution I will use here is very common in Haskell: it is to use "Maybe". If the string is correct, it will return "Just result" else it will return "Nothing". Let's see that in practice!
The first function we will write is to convert a char to a binary. As discussed above, Nothing represents an error.
charToBinary :: Char -> Maybe Binary
charToBinary '0' = Just Zero
charToBinary '1' = Just One
charToBinary _ = Nothing
Then, we can write a function for a whole string (which is a list of Char). So [Char] is equivalent to String. I used it here to make clearer that we are dealing with a list.
stringToBinary :: [Char] -> Maybe [Binary]
stringToBinary [] = Just []
stringToBinary chars = mapM charToBinary chars
The function mapM is a kind of variation of map which acts on monads (Maybe is actually a monad). To learn about monads I recommend reading Learn You a Haskell for Great Good!
http://learnyouahaskell.com/a-fistful-of-monads
We can notice once more that if there are any errors, Nothing will be returned.
A dedicated function to convert strings holding binaries can now be written.
binStringToDecimal :: [Char] -> Maybe Integer
binStringToDecimal = fmap binToDecimal . stringToBinary
The use of the "." function allow us to define this function as an equality with another function, so we do not need to mention the parameter (point free notation).
The fmap function allow us to run binToDecimal (which expect a [Binary] as argument) on the return of stringToBinary (which is of type "Maybe [Binary]"). Once again, Learn you a Haskell... is a very good reference to learn more about fmap:
http://learnyouahaskell.com/functors-applicative-functors-and-monoids
Now, we can run a second test:
test2 = binStringToDecimal "101010"
> Just 42
And finally, we can test our error handling system with a mistake in the string:
test3 = binStringToDecimal "102010"
> Nothing

Why doesn't GHC give a compile time warning for the "No match in record selector" exception?

When I run this buggy code...
data Person = Adult { pName :: String}
| Kid { pName :: String
, pAge :: Int
} deriving Show
getAge :: Person -> Int
getAge p = pAge p
getName :: Person -> String
getName p = pName p
main :: IO ()
main = do
let p1 = Kid "fred" 5
p2 = Adult "john"
ps = [p1, p2]
names = map getName ps
ages = map getAge ps
putStrLn $ "names: " ++ show names
putStrLn $ "ages: " ++ show ages
... I get this in ghci:
names: ["fred","john"]
ages: [5,* * * Exception: No match in record selector pAge
I know how to avoid this error, but I'm wondering why compiling with "ghc -Wall" didn't warn me about this problem. Is there another tool that can help me to prevent this type of error?
Is there [a] tool that can help me to prevent this type of error?
No, but there could be.
As you know, record syntax automatically generates getters with the same name as the attributes you define. Therefore the code
data Person = Adult { pName :: String}
| Kid { pName :: String
, pAge :: Int
} deriving Show
creates the functions pName :: Person -> String and pAge :: Person -> Int. Now, suppose Haskell had subtyping. If it did, then Kid could be a subtype of Person, and pAge could have the more appropriate type Kid -> String. However, Haskell does not have subtyping, and there is therefore no Kid type.
Now, given that Person -> String is the most specific type we can give to pAge, why not warn that pAge is a partial function at compile time? Let me divert the question by referring to the List example
data List a = Cons { head :: a, tail :: List a } | Empty
In this example, head and tail are partial functions: the two components of a non-empty list, but (due to Haskell's lack of subtyping) meaningless accessors on the empty list. So, why no warning by default? Well, by default, you know the code you have written. The compiler doesn't provide warnings if you use unsafePerformIO, because you're the programmer here, you're expected to use such things responsibly.
So tl;dr: if you want the warning here:
getAge :: Person -> Int
getAge p = pAge p
then you're out of luck, because the type system does not have enough information to deduce that this is a problem.
If you want the warning here:
data Person = Adult | Kid { pAge :: Int }
then I'm sure it would be trivial to implement: just check that a given field exists in some constructors but not others. But I do not foresee this warning being widely useful for everyone; some might complain that it would be just noise.
I'd be surprised if http://community.haskell.org/~ndm/catch/ doesn't pick this up.
It does, since 8.4, with -Wpartial-fields.
https://downloads.haskell.org/ghc/latest/docs/html/users_guide/using-warnings.html#ghc-flag--Wpartial-fields

Storing values in a data structure Haskell

I'm trying to store randomly generated dice values in some data structure, but don't know how exactly to do it in Haskell. I have so far, only been able to generate random ints, but I want to be able to compare them to the corresponding color values and store the colors instead (can't really conceive what the function would look like). Here is the code I have --
module Main where
import System.IO
import System.Random
import Data.List
diceColor = [("Black",1),("Green",2),("Purple",3),("Red",4),("White",5),("Yellow",6)]
diceRoll = []
rand :: Int -> [Int] -> IO ()
rand n rlst = do
num <- randomRIO (1::Int, 6)
if n == 0
then printList rlst -- here is where I need to do something to store the values
else rand (n-1) (num:rlst)
printList x = putStrLn (show (sort x))
--matchColor x = doSomething()
main :: IO ()
main = do
--hSetBuffering stdin LineBuffering
putStrLn "roll, keep, score?"
cmd <- getLine
doYahtzee cmd
--rand (read cmd) []
doYahtzee :: String -> IO ()
doYahtzee cmd = do
if cmd == "roll"
then do rand 5 []
else putStrLn "Whatever"
After this, I want to be able to give the user the ability to keep identical dices (as in accumulate points for it) and give them a choice to re-roll the left over dices - I'm thinking this can done by traversing the data structure (with the dice values) and counting the repeating dices as points and storing them in yet another data structure. If the user chooses to re-roll he must be able to call random again and replace values in the original data structure.
I'm coming from an OOP background and Haskell is new territory for me. Help is much appreciated.
So, several questions, lets take them one by one :
First : How to generate something else than integers with the functions from System.Random (which is a slow generator, but for your application, performance isn't vital).
There is several approaches, with your list, you would have to write a function intToColor :
intToColor :: Int -> String
intToColor n = head . filter (\p -> snd p == n) $ [("Black",1),("Green",2),("Purple",3),("Red",4),("White",5),("Yellow",6)]
Not really nice. Though you could do better if you wrote the pair in the (key, value) order instead since there's a little bit of support for "association list" in Data.List with the lookup function :
intToColor n = fromJust . lookup n $ [(1,"Black"),(2,"Green"),(3,"Purple"),(4,"Red"),(5,"White"),(6,"Yellow")]
Or of course you could just forget this business of Int key from 1 to 6 in a list since lists are already indexed by Int :
intToColor n = ["Black","Green","Purple","Red","White","Yellow"] !! n
(note that this function is a bit different since intToColor 0 is "Black" now rather than intToColor 1, but this is not really important given your objective, if it really shock you, you can write "!! (n-1)" instead)
But since your colors are not really Strings and more like symbols, you should probably create a Color type :
data Color = Black | Green | Purple | Red | White | Yellow deriving (Eq, Ord, Show, Read, Enum)
So now Black is a value of type Color, you can use it anywhere in your program (and GHC will protest if you write Blak) and thanks to the magic of automatic derivation, you can compare Color values, or show them, or use toEnum to convert an Int into a Color !
So now you can write :
randColorIO :: IO Color
randColorIO = do
n <- randomRIO (0,5)
return (toEnum n)
Second, you want to store dice values (colors) in a data structure and give the option to keep identical throws. So first you should stock the results of several throws, given the maximum number of simultaneous throws (5) and the complexity of your data, a simple list is plenty and given the number of functions to handle lists in Haskell, it is the good choice.
So you want to throws several dices :
nThrows :: Int -> IO [Color]
nThrows 0 = return []
nThrows n = do
c <- randColorIO
rest <- nThrows (n-1)
return (c : rest)
That's a good first approach, that's what you do, more or less, except you use if instead of pattern matching and you have an explicit accumulator argument (were you going for a tail recursion ?), not really better except for strict accumulator (Int rather than lists).
Of course, Haskell promotes higher-order functions rather than direct recursion, so let's see the combinators, searching "Int -> IO a -> IO [a]" with Hoogle gives you :
replicateM :: Monad m => Int -> m a -> m [a]
Which does exactly what you want :
nThrows n = replicateM n randColorIO
(I'm not sure I would even write this as a function since I find the explicit expression clearer and almost as short)
Once you have the results of the throws, you should check which are identical, I propose you look at sort, group, map and length to achieve this objective (transforming your list of results in a list of list of identical results, not the most efficient of data structure but at this scale, the most appropriate choice). Then keeping the colors you got several time is just a matter of using filter.
Then you should write some more functions to handle interaction and scoring :
type Score = Int
yahtzee :: IO Score
yahtzeeStep :: Int -> [[Color]] -> IO [[Color]] -- recursive
scoring :: [[Color]] -> Score
So I recommend to keep and transmit a [[Color]] to keeps track of what was put aside. This should be enough for your needs.
You are basically asking two different questions here. The first question can be answered with a function like getColor n = fst . head $ filter (\x -> snd x == n) diceColor.
Your second question, however, is much more interesting. You can't replace elements. You need a function that can call itself recursively, and this function will be driving your game. It needs to accept as parameters the current score and the list of kept dice. On entry the score will be zero and the kept dice list will be empty. It will then roll as many dice as needed to fill the list (I'm not familiar with the rules of Yahtzee), output it to the user, and ask for choice. If the user chooses to end the game, the function returns the score. If he chooses to keep some dice, the function calls itself with the current score and the list of kept dice. So, to sum it up, playGame :: Score -> [Dice] -> IO Score.
Disclaimer: I am, too, very much a beginner in Haskell.
at first thought:
rand :: Int -> IO [Int]
rand n = mapM id (take n (repeat (randomRIO (1::Int, 6))))
although the haskellers could remove the parens

Haskell beginner, trying to output a list

I suppose everyone here already has seen one of these (or at least a similar) question, still I need to ask because I couldn't find the answer to this question anywhere (mostly because I don't know what exactly I should be looking for)
I wrote this tiny script, in which printTriangle is supposed to print out the pascal triangle.
fac = product . enumFromTo 2
binomial n k = (product (drop (k-1) [2..n])) `div` (fac (n-k))
pascalTriangle maxRow =
do row<-[0..maxRow-1]
return (binomialRow row)
where
binomialRow row =
do k<-[0..row]
return (binomial row k)
printTriangle :: Int -> IO ()
printTriangle rows = do row<-(triangle)
putStrLn (show row)
where
triangle = pascalTriangle rows
Now for reasons that are probably obvious to the trained eye, but completely shrouded in mystery for me, i get the following error when trying to load this in ghci:
Couldn't match expected type `IO t0' with actual type `[[Int]]'
In a stmt of a 'do' expression: row <- (triangle)
In the expression:
do { row <- (triangle);
putStrLn (show row) }
In
an equation for `printTriangle':
printTriangle rows
= do { row <- (triangle);
putStrLn (show row) }
where
triangle = pascalTriangle rows
what im trying to do is something like I call printTriangle like this:
printTriangle 3
and I get this output:
[1]
[1,1]
[1,2,1]
If anyone could explain to me why what I'm doing here doesn't work (to be honest, I am not TOO sure what exactly I am doing here; I am used to imperative languages and this whole functional programming thingy is still mighty confusing to me), and how I could do it in a less dumb fashion that would be great.
Thanks in advance.
You said in a comment that you thought lists were monads, but now you're not sure -- well, you're right, lists are monads! So then why doesn't your code work?
Well, because IO is also a monad. So when the compiler sees printTriangle :: Int -> IO (), and then do-notation, it says "Aha! I know what to do! He's using the IO monad!" Try to imagine its shock and dispair when it discovers that instead of IO monads, it finds list monads inside!
So that's the problem: to print, and deal with the outside world, you need to use the IO monad; inside the function, you're trying to use lists as the monad.
Let's see how this is a problem. do-notation is Haskell's syntactic sugar to lure us into its cake house and eat us .... I mean it's syntactic sugar for >>= (pronounced bind) to lure us into using monads (and enjoying it). So let's write printTriangle using bind:
printTriangle rows = (pascalTriangle rows) >>= (\row ->
putStrLn $ show row)
Okay, that was straightforward. Now do we see any problems? Well, lets look at the types. What's the type of bind? Hoogle says: (>>=) :: Monad m => m a -> (a -> m b) -> m b. Okay, thanks Hoogle. So basically, bind wants a monad type wrapping a type a personality, a function that turns a type a personality into (the same) monad type wrapping a type-b personality, and ends up with (the same) monad type wrapping a type-b personality.
So in our printTriangle, what do we have?
pascalTriangle rows :: [[Int]] -- so our monad is [], and the personality is [Int]
(\row -> putStrLn $ show row) :: [Int] -> IO () -- here the monad is IO, and the personality is ()
Well, crap. Hoogle was very clear when it told us that we had to match our monad types, and instead, we've given >>= a list monad, and a function that produces an IO monad. This makes Haskell behave like a little kid: it closes its eyes and stomps on the floor screaming "No! No! No!" and won't even look at your program, much less compile it.
So how do we appease Haskell? Well, others have already mentioned mapM_. And adding explicit type signatures to top-level functions is also a good idea -- it can sometimes help you to get compile errors sooner, rather than later (and get them you will; this is Haskell after all :) ), which makes it much much easier to understand the error messages.
I'd suggest writing a function that turns your [[Int]] into a string, and then printing the string out separately. By separating the conversion into a string from the IO-nastiness, this will allow you to get on with learning Haskell and not have to worry about mapM_ & friends until you're good and ready.
showTriangle :: [[Int]] -> String
showTriangle triangle = concatMap (\line -> show line ++ "\n") triangle
or
showTriangle = concatMap (\line -> show line ++ "\n")
Then printTriangle is a lot easier:
printTriangle :: Int -> IO ()
printTriangle rows = putStrLn (showTriangle $ pascalTriangle rows)
or
printTriangle = putStrLn . showTriangle . pascalTriangle
If you want to print elements of a list on new lines you shall see this question.
So
printTriangle rows = mapM_ print $ pascalTriangle rows
And
λ> printTriangle 3
[1]
[1,1]
[1,2,1]
Finally, what you're asking for is seems to be mapM_.
Whenever I'm coding in Haskell I always try declare the types of at least the top-level definitions. Not only does it help by documenting your functions, but also makes it easier to catch type errors. So pascalTriangle has the following type:
pascalTriangle :: Int -> [[Int]]
When the compiler sees the lines:
row<-(triangle)
...
where
triangle = pascalTriangle rows
it will infer that triangle has type:
triangle :: [[Int]]
The <- operator expects it's right-hand argument to be a monad. Because you declared your function to work on IO monad, the compiler expected that triangle had the type:
triangle :: IO something
Which clearly does not match type [[Int]]. And that's kind of what the compiler is trying to tell in it's own twisted way.
As others have stated, that style of coding is not idiomatic Haskell. It looks like the kind of code I would produce in my early Haskell days, when I still had an "imperative-oriented" mind. If you try to put aside imperative style of thinking, and open your mind to the functional style, you will find that you can solve most of your problems in a very elegant and tidy fashion.
try the following from the ghci-prompt:
> let {pascal 1 = [1]; pascal n = zipWith (+) (l++[0]) (0:l) where l = pascal (n-1)}
> putStr $ concatMap ((++"\n") . show . pascal) [1..20]
Your code is very unidiomatic Haskell. In Haskell you use higher order function to build other function. That way you can write very concise code.
Here i combine two list lazily using zipWith to produce the next row of pascals triangle pretty much the way you would compute it by hand. Then concatMap is used to produce a printable string of the triangles which is printed by putStr.

Resources