Converting [[Maybe Int]] to IO () - haskell

After going through a couple of chapters of "Learn You A Haskell", I wanted to write something hands on and decided to implement a Sudoku solver.I am trying to implement the B1 function from here: http://www.cse.chalmers.se/edu/year/2013/course/TDA555/lab3.html
My code:
data Sudoku = Sudoku { getSudoku :: [[Maybe Int]] } deriving (Show, Eq)
rows :: Sudoku -> [[Maybe Int]]
rows (Sudoku rs) = rs
example :: Sudoku
example = Sudoku
[ [Just 3, Just 6, Nothing,Nothing,Just 7, Just 1, Just 2, Nothing,Nothing]
, [Nothing,Just 5, Nothing,Nothing,Nothing,Nothing,Just 1, Just 8, Nothing]
, [Nothing,Nothing,Just 9, Just 2, Nothing,Just 4, Just 7, Nothing,Nothing]
, [Nothing,Nothing,Nothing,Nothing,Just 1, Just 3, Nothing,Just 2, Just 8]
, [Just 4, Nothing,Nothing,Just 5, Nothing,Just 2, Nothing,Nothing,Just 9]
, [Just 2, Just 7, Nothing,Just 4, Just 6, Nothing,Nothing,Nothing,Nothing]
, [Nothing,Nothing,Just 5, Just 3, Nothing,Just 8, Just 9, Nothing,Nothing]
, [Nothing,Just 8, Just 3, Nothing,Nothing,Nothing,Nothing,Just 6, Nothing]
, [Nothing,Nothing,Just 7, Just 6, Just 9, Nothing,Nothing,Just 4, Just 3]
]
printSudoku :: Sudoku -> IO ()
printSudoku s = do
print . map (map (\x -> if isNothing x then 0 else fromJust x)) $ rows s
I am trying to get it to print as
Sudoku> printSudoku example
36..712..
.5....18.
..92.47..
....13.28
4..5.2..9
27.46....
..53.89..
.83....6.
..769..43
but I can only get it to print as
[[3,6,0,0,7,1,2,0,0],[0,5,0,0,0,0,1,8,0],[0,0,9,2,0,4,7,0,0],[0,0,0,0,1,3,0,2,8],[4,0,0,5,0,2,0,0,9],[2,7,0,4,6,0,0,0,0],[0,0,5,3,0,8,9,0,0],[0,8,3,0,0,0,0,6,0],[0,0,7,6,9,0,0,4,3]]
I apologize if this is the wrong place for such beginner questions. It's just that I have been trying for a while and getting stuck on something relatively trivial and its getting frustrating. Thanks

You are very near!
The key point is this anonymous function:
(\x -> if isNothing x then 0 else fromJust x)
BTW, there are 2 warning flags here: The use of isNothing and fromJust.
Now, as this function returns numbers, you can have only numbers displayed. But you want characters instead. Hence, just rewrite this as a local function like:
showcell Nothing = '.'
showcell (Just n) = ....
=== EDIT: More general advice ===
Whenever you find yourself writing:
if isNothing x then a else f (fromJust x)
you should replace it with an explicit local function or
maybe a f x
In your case, you'd initially written just:
(\x -> maybe 0 id x)
which reduces to the much nicer
maybe 0 id
and now you just had to change it to:
maybe '.' (head . show)
or something.

Related

How to Set Slices in Haskell's HMatrix?

Haskell's HMatrix allows you to conveniently get slices:
m ?? (All, Take 3)
But how can you set slices, especially non-rectangular ones? For instance, in Python's Numpy I'd do:
>>> x = np.arange(12).reshape(3, 4)
>>> x
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> x[[0,0], [1,3]] += x[[2,2], [1,3]] # to ix (0, 1) add (2, 1) and to ix (0, 3) add (2, 3)
>>> x
array([[ 0, 10, 2, 14],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
I'm able to write this helper function myself, but, it's sure ugly, and partial, and required I add zipWith3M_ which should exist in the vector library but doesn't:
setSlice :: (Element t, Num t) => Matrix t -> (Extractor, Extractor) -> Vector t -> Matrix t
setSlice parent (Pos (V.map fromIntegral -> irows), Pos (V.map fromIntegral -> icols)) sub = runST $ do
tparent <- thawMatrix parent
zipWith3M_ (writeMatrix tparent) irows icols sub
freezeMatrix tparent

How to return a list of names in Haskell?

I am writing a simple program that deals with rainfall for places in the UK. Each place has a name, location in degrees north and east, and list of rainfall figures.
How do I return a list of the names of all places, example:
[London, Cardiff, St Helier].
Error:
1. Couldn't match type
2. list comprehension
import Data.Char
import Data.List
type Place = (String, Int, Int, [Int])
testData :: [Place]
testData = [("London", 51.5, -0.1, [0, 0, 5, 8, 8, 0, 0]),
("Cardiff", 51.5, -3.2, [12, 8, 15, 0, 0, 0, 2]),
("St Helier", 49.2, -2.1, [0, 0, 0, 0, 6, 10, 0])]
listNames :: Place -> [String]
listNames details = [name | (name,north,east,[figure]) <- details]
There are several problems with your current solution:
type Place = (String, Int, Int, [Int]) but ("London", 51.5, -0.1, [0, 0, 5, 8, 8, 0, 0]) The problem here is that you have specified the two middle fields of the tuple to be Ints, but you pass in 51.5 and -0.1, which are fractional values. I would recommend changing Place to: type Place = (String, Float, Float, [Int]) (you could also look into using a record).
Your listNames function's signature epxects only a single place: listNames :: Place -> [String], but you actually mean to have it take a list of places. You should change it to listNames :: [Place] -> [String].
Your list comprehension uses a restrictive pattern match, while you want one that accepts pretty much anything: the [figure] part of the pattern match only matches a list with a single element, which you are binding to figure. Make sure that you understand the difference between the list type notation [a] and the list constructor [1, 2, 3].
Not only that, but you can disregard all but the place name anyway: [name | (name, _, _, _) <- details].
All together, your code would become:
type Place = (String, Float, Float, [Int])
testData :: [Place]
testData = [("London", 51.5, -0.1, [0, 0, 5, 8, 8, 0, 0]),
("Cardiff", 51.5, -3.2, [12, 8, 15, 0, 0, 0, 2]),
("St Helier", 49.2, -2.1, [0, 0, 0, 0, 6, 10, 0])]
listNames :: [Place] -> [String]
listNames details = [name | (name, _, _, _) <- details]

Elm quicksort visualization

I'm trying to display the sorting process of quicksort with Elm
[ 5, 8, 6, 2, 4, 1, 0, 3, 10, 7, 9 ]
[2,4,1,0,3] 5 [8,6,10,7,9]
[1,0] 2 [4,3] [6,7] 8 [10,9]
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
Right now i can get the first 2 lines but I'm unsure how to approach this in a recursive manner.
list_to_html : List (List Int) -> Html msg
list_to_html x =
div [] [ x |> toString |> text ]
quicksort_partition : List Int -> Html msg
quicksort_partition list =
case list of
x :: xs ->
let
lower =
List.filter ((>=) x) xs
higher =
List.filter ((<) x) xs
in
list_to_html [ lower, [ x ], higher ]
[] ->
list_to_html []
This outputs:
[ 5, 8, 6, 2, 4, 1, 0, 3, 10, 7, 9 ]
[2,4,1,0,3] [5] [8,6,10,7,9]
If you are trying to get that kind of output, direct recursion inside the view isn't going to work well. Instead, I would approach it as writing a variation of quicksort which logs the state along the way.
Here is an example of quicksort which also returns a list of logs. The type aliases are included to try and make the function annotation more clear:
type alias Depth =
Int
type alias Log comparable =
( Depth, List comparable, comparable, List comparable )
quicksortLog : Depth -> List comparable -> ( List comparable, List (Log comparable) )
quicksortLog depth list =
case list of
[] ->
( [], [] )
x :: xs ->
let
( lower, lowerLog ) =
quicksortLog (depth + 1) (List.filter ((>=) x) xs)
( higher, higherLog ) =
quicksortLog (depth + 1) (List.filter ((<) x) xs)
log =
( depth, lower, x, higher )
in
( lower ++ [ x ] ++ higher, log :: lowerLog ++ higherLog )
Given that result, you could then write a view which displays the data in the way you see fit.

What does the double-backslash \\ mean in Haskell?

I'm trying to figure out what \\ means in Haskell?
I've got a program that runs perfectly when compiled, implying that \\ is a built-in function, since it's not defined anywhere in the program. However, in GHCi, if I try to use it in the same manner, I get an error saying it's not in the scope.
Does it mean something special in each context?
Here is my code;
module Main where
import Data.List
numbersA = [1, 105, 103, 7, 4, 102, 3, 101, 107, 8, 9]
numbersB = [6, 9, 7, 8, 1, 5, 3, 2, 4]
type Number = Integer
type Run = [Number]
extractRuns :: [Number] -> [Run]
extractRuns [] = []
extractRuns xs = run : extractRuns xs'
where run = buildRun (head xs) (tail xs)
xs' = xs \\ run
buildRun :: Number -> [Number] -> Run
buildRun seed numbers
| endRun = [seed]
| otherwise = seed : buildRun seed' numbers'
where endRun = successors == []
successors = filter (.#. seed) numbers
numbers' = numbers \\ [seed]
seed' = head successors
(.#.) :: Number -> Number -> Bool
x .#. y = x /= y && abs (x - y) < 10
runs = extractRuns numbersA
main = print runs
\\ is the list difference operator. You can use it in GHCi you just have to import Data.List first.
Prelude> :m Data.List
Prelude Data.List> [1..5]\\[3,4]
[1,2,5]
On a sidenote, this is why I'd suggest avoiding mass imports like import Data.List and to be more specific import Data.List ( (\\) ) so you can be more aware of just what you're importing.
It is the list difference operation. Figuring things like this out is easy if you know to use hoogle.

How to build diagonal matrix with list comprehension

How can I build an infinite matrix with numbers placed in it diagonally with list comprehension?
[[ 1, 2, 4, 7, 11, ...],
[ 3, 5, 8, 12, 17, ...],
[ 6, 9, 13, 18, 24, ...],
[10, 14, 19, 25, 32, ...],
...]
I've tried to do it like this:
firstColumn = take 6 $ map fst $ iterate (\(a,b) -> (a+b,b+1)) (1,2)
matr :: [[Int]]
matr = [take 6 $ map fst $ iterate (\(x,y) -> (x+y, y+1)) (a, i) | a <- firstColumn, let i = 1]
But how can I pass (i + 1) to next every row (in other words, how do I iterate for additional rows)
By finding a formula for the x and y indices, f.e.:
[[ 1 + (x + y) * (x + y + 1) `div` 2 + y | x <- [0..]] | y <- [0..]]

Resources