I am new to sml, now I am trying to define a zip function which takes two lists as a tuple.
here are the code.
I got it working, but I have a few questions
exception Mismatch;
fun zip ([],[]) = []
| zip ((x::xs),(y::ys)) = (x, y)::zip (xs, ys)
| zip (_, _) = raise Mismatch;
Can I define the exception inside zip function, like let in end, I tried, but always get error.
Another question is for the second pattern matching, I wrote
zip ([x::xs],[y::ys]) = (x, y)::zip (xs, ys)
also gave me error.
Zip take a tuple, but each of the element is list, why can't I use [x::xs] just like other list?
last question, in pattern matching, does the order matter? I think it is, I change the order and got error, just want to make sure
Thanks
You should never define an exception inside of a let ... in ... end*. It makes it impossible to catch it by name outside of the let-expression.
*: It's okay if you don't plan on letting it escape from the let-expression, but you do plan on doing that here.
As for your other question:
When you write [...], the SML compiler understands it as "The list containing ...."
E.g, [1] is the list containing 1, [4, 6, 2] is the list containing 4, 6 and 2, and so on.
When you write x :: xs, the SML compiler understands it as "The list starting with x, followed by the list xs."
E.g. 1 :: [] is the list starting with a 1, followed by the empty list, and 4 :: [6, 2] is the list starting with a 4, followed by 6 and 2, and so on.
Now, when you write [x :: xs], you're doing a combination of the two, and SML understands it as: "The list containing the list starting with x, followed by xs."
So, by writing [...] rather than (...), you're asking for a list within another list. This is not what you want.
For your final question: Yes, order matters. Patterns are checked in top-down order. Therefore,
fun foo _ = 4
| foo 4 = 5
will always return 4, whereas
fun foo 4 = 5
| foo _ = 4
will return 5 when given a 4.
Related
There is a case mapping two vectors into a single vector. I expected that the result of both ML should be same. Unfortunately, the result of ReasonML is different. Please help and comment how to fix it.
OCaml
List.map2 (fun x y -> x+y) [1;2;3] [10;20;30];;
[11;;22;;33]
ReasonML
Js.log(List.map2 ( (fun (x,y) => x+y), [1,2,3], [10,20,30]))
[11,[22,[33,0]]]
This is the same result. If you run:
Js.log([11,22,33]);
You'll get:
[11,[22,[33,0]]]
The result is the same, but you're using different methods of printing them. If instead of Js.log you use rtop or sketch.sh, you'll get the output you expect:
- : list(int) = [11, 22, 33]
Js.log prints it differently because it is a BuckleScript binding to console.log, which will print the JavaScript-representation of the value you give to it. And lists don't exist in JavaScript, only arrays do.
The way BuckleScript represents lists is pretty much the same way it is done natively. A list in OCaml and Reason is a "cons-cell", which is essentially a tuple or a 2-element array, where the first item is the value of that cell and the last item is a pointer to the next cell. The list type is essentially defined like this:
type list('a) =
| Node('a, list('a))
| Empty;
And with this definition could have been constructed with:
Node(11, Node(22, Node(33, Empty)))
which is represented in JavaScript like this:
[11,[22,[33,0]]]
^ ^ ^ ^
| | | The Empty list
| | Third value
| Second value
First value
Lists are defined this way because immutability makes this representation very efficient. Because we can add or remove values without copying all the items of the old list into a new one. To add an item we only need to create one new "cons-cell". Using the JavaScript representation with imagined immutability:
const old = [11,[22,[33,0]]];
const new = [99, old];
And to remove an item from the front we don't have to create anything. We can just get a reference to and re-use a sub-list, because we know it won't change.
const old = [11,[22,[33,0]]];
const new = old[1];
The downside of lists is that adding and removing items to the end is relatively expensive. But in practice, if you structure your code in a functional way, using recursion, the list will be very natural to work with. And very efficient.
#Igor Kapkov, thank you for your help. Base on your comment, I found a pipeline statement in the link, there is a summary.
let a = List.map2 ( (fun (x,y) => x+y), [1,2,3], [10,20,30] )
let logl = l => l |> Array.of_list |> Js.log;
a |> logl
[11,22,33]
I am a complete beginner to Haskell but I'm being asked to create a sudoku solver. I've been making some steady progress with it but one of the things it is asking me to do is print a valid representation of a sudoku puzzle s. The Puzzle data type is defined as a list of lists, so [[Maybe Int]] and this is composed of Block values ([Maybe Int], representing a row).
Function signature is this:
printPuzzle :: Puzzle -> IO ()
How do I output this? I know this may be a simple question and I'm missing the point but I'm still not at the stage where I've got my ahead around the syntax yet. Any help would be much appreciated!
Simple pretty-printing of this can be done really succinctly with something like the following:
import Data.Char (intToDigit)
showRow :: [Maybe Int] -> String
showRow = map (maybe ' ' intToDigit)
showPuzzle :: [[Maybe Int]] -> [String]
showPuzzle = map showRow
printPuzzle :: [[Maybe Int]] -> IO ()
printPuzzle = mapM_ putStrLn . showPuzzle
showRow takes a single row from your grid and prints it - using the maybe function from Data.Maybe, we can write this as a quick map from each Maybe Int value to either a default "blank space" value or the character representing the number (using intToDigit).
showPuzzle simply maps showRow over the outer list.
printPuzzle just uses the previous pure definitions to give the impure action which prints a grid, by putStrLn'ing the pretty-print of each row.
A quick demo:
> printPuzzle [[Just 1, Nothing, Just 3],
[Nothing, Just 3, Just 6],
[Just 2, Just 4, Just 5]]
1 3
36
245
Though you can easily modify the above code to print something more explicit, like:
1X3
X36
245
I'm wondering how to obtain the unique values from a list by using Haskell list comprehension. So if I were to enter [2,4,5,4,4,6,2] it would return [2,4,5,6].
Initially I started with unique (y:ys) = [x | x <- (y:ys)] and I know I need some other condition on x, but am not sure how to get there.
The comment from #amalloy that list comprehensions are confined to a "local" perspective is the key insight here. There is a sensible way to write nub as a list comprehension, but you first need to change your perspective.
An often useful function sadly omitted from the library is the function which decorates each element of a list with its context.
picks :: [x] -> [([x], x, [x])]
picks [] = []
picks (x : xs) = ([], x, xs) : [(x : bs, y, as) | (bs, y, as) <- picks xs]
So
picks [1,2,3] =
[([],1,[2,3]), ([1],2,[3]), ([1,2],3,[])]
Each element of the list is put in the middle of a triple, with the elements 'before' to its left and the elements 'after' to its right.
This answer of mine explains the deep structure which makes picks in some sense a "standard" operation, derivable from the structure of lists. But we don't need that background information to deploy it.
The picks function gives us exactly the contextual information we need to write nub as a list comprehension. All we need to do is pick out the elements which don't occur in their own 'before lists'.
myNub :: Eq x => [x] -> [x]
myNub xs = [x | (bs, x, as) <- picks xs, not (elem x bs)]
I make no promises as to the efficiency of this operation, but I do like the clarity that comes from combining list comprehensions with extra spatial context.
You could do it in a (perhaps needlessly clever) way with laziness, by starting with a bit of circular reasoning: each element of the input should appear in the output, only if it hasn’t appeared in the output.
That is, for an input list like [0, 0, 1], the first 0 should be added but the second 0 should not.
Clearly, something like this won’t work:
unique xs = us
where us = [x | x <- xs, x `notElem` us]
Because it will get stuck in an infinite loop, trying to test elements of the output that haven’t been generated yet. What you can do instead is change the reasoning to this: each element of the input should appear in the output, only if it hasn’t already appeared in the output.
You can implement this directly by considering what “already” means: the current value must not have appeared at an index before the current index.
unique xs = catMaybes us
where
us =
[ if Just x `elem` take i us -- If the element has appeared before here
then Nothing -- then don’t include it again
else Just x -- otherwise do include it.
| (i, x) <- zip [0..] xs -- (Zip the elements with their indices.)
]
So for the input list xs = [0, 0, 1], this would generate xs' = [Just 0, Nothing, Just 1], which would be flattened by catMaybes into [0, 1]. Testing with QuickCheck confirms this is equivalent to nub, and halts because we only check the first take i elements of us at each step, ensuring that we don’t examine any elements that haven’t been generated yet.
It’s worth noting that, like nub, this is O(n2) in the length of the input.
So I'm writing a line to get the second to last element of a list. Initially my code was
mySLast x = last.take ((length x) - 1) x
Which worked up until the last function. Realized the my take business is already included in Haskell as init so I rewrote as
mySLast = last.init
This still doesn't work. I find this puzzling because init::[a]->[a] and last::[a]->a so they definitely should be composable morphisms in the Hask Category.
I tried asking Haskell what it thinks the type is and it said
ghci> :t last.init
last.init :: [c] -> c
ghci> last.init [3,2,4,1]
<interactive>:45:6:
Couldn't match expected type ‘a -> [c]’
with actual type ‘[Integer]’
Relevant bindings include
it :: a -> c (bound at <interactive>:45:1)
Possible cause: ‘init’ is applied to too many arguments
In the second argument of ‘(.)’, namely ‘init [3, 2, 4, 1]’
In the expression: last . init [3, 2, 4, 1]
Even though
ghci> init [3,2,4,1]
[3,2,4]
ghci> last [3,2,4]
4
So I must be misunderstanding something about composing functions in Haskell. Any insight would be greatly appreciated!
Function application binds more tightly than (.) so
last.init [3,2,4,1]
is being parsed as
last . (init [3,2,4,1])
you can use
(last . init) [3,2,4,1]
or
last . init $ [3,2,4,1]
You forgot the $ between init and your list, e.g.
last . init $ [3,2,4,1]
↑ See here
An alternative solution to this problem that only evaluates the (spine of the) list up to the needed element, rather than using length (which will evaluate the entire spine before walking back to the needed element):
takeTail n xs = go (drop n xs) xs
where
go (_:ys) (_:xs) = go ys xs
go [] xs = xs -- Stop and return xs when ys runs out
> head . takeTail 2 $ [1,2,3,4]
3
ZipList comes with a Functor and an Applicative instance (Control.Applicative) but why not Alternative?
Is there no good instance?
What about the one proposed below?
Is it flawed?
is it useless?
Are there other reasonable possibilities (like Bool can be a monoid in two ways) and therefore neither should be the instance?
I searched for "instance Alternative ZipList" (with the quotes to find code first) and only found the library, some tutorials, lecture notes yet no actual instance.
Matt Fenwick said ZipList A will only be a monoid if A is (see here). Lists are monoids though, regardless of the element type.
This other answer by AndrewC to the same question discusses how an Alternative instance might look like. He says
There are two sensible choices for Zip [1,3,4] <|> Zip [10,20,30,40]:
Zip [1,3,4] because it's first - consistent with Maybe
Zip [10,20,30,40] because it's longest - consistent with Zip [] being discarded
where Zip is basically ZipList.
I think the answer should be Zip [1,3,4,40]. Let's see the instance:
instance Aternative Zip where
empty = Zip []
Zip xs <|> Zip ys = Zip (go xs ys) where
go [] ys = ys
go (x:xs) ys = x : go xs (drop 1 ys)
The only Zip a we can produce without knowing the type argument a is Zip [] :: Zip a, so there is little choice for empty. If the empty list is the neutral element of the monoid, we might be tempted to use list concatenation. However, go is not (++) because of the drop 1. Every time we use one entry of the first argument list, we drop one off the second as well. Thus we have a kind of overlay: The left argument list hides the beginning of the right one (or all of it).
[ 1, 3, 4,40] [10,20,30,40] [ 1, 3, 4] [ 1, 3, 4]
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
| | | | | | | | | | | | | |
[ 1, 3, 4] | [10,20,30,40] []| | | [ 1, 3, 4]
[10,20,30,40] [ 1, 3, 4] [ 1, 3, 4] []
One intuition behind ziplists is processes: A finite or infinite stream of results. When zipping, we combine streams, which is reflected by the Applicative instance. When the end of the list is reached, the stream doesn't produce further elements. This is where the Alternative instance comes in handy: we can name a concurrent replacement (alternative, really), taking over as soon as the default process terminates.
For example we could write fmap Just foo <|> pure Nothing to wrap every element of the ziplist foo into a Just and continue with Nothing afterwards. The resulting ziplist is infinite, reverting to a default value after all (real) values have been used up. This could of course be done by hand, by appending an infinite list inside the Zip constructor. Yet the above is more elegant and does not assume knowledge of constructors, leading to higher code reusability.
We don't need any assumption on the element type (like being a monoid itself). At the same time the definition is not trivial (as (<|>) = const would be). It makes use of the list structure by pattern matching on the first argument.
The definition of <|> given above is associative and the empty list really is the empty element. We have
Zip [] <*> xs == fs <*> Zip [] == Zip [] -- 0*x = x*0 = 0
Zip [] <|> xs == xs <|> Zip [] == xs -- 0+x = x+0 = x
(fs <|> gs) <*> xs == fs <*> xs <|> gs <*> xs
fs <*> (xs <|> ys) == fs <*> xs <|> fs <*> ys
so all the laws you could ask for are satisfied (which is not true for list concatenation).
This instance is consistent with the one for Maybe: choice is biased to the left, yet when the left argument is unable to produce a value, the right argument takes over. The functions
zipToMaybe :: Zip a -> Maybe a
zipToMaybe (Zip []) = Nothing
zipToMaybe (Zip (x:_)) = Just x
maybeToZip :: Maybe a -> Zip a
maybeToZip Nothing = Zip []
maybeToZip (Just x) = Zip (repeat x)
are morphisms of alternatives (meaning psi x <|> psi y = psi (x <|> y) and psi x <*> psi y = psi (x <*> y)).
Edit: For the some/many methods I'd guess
some (Zip z) = Zip (map repeat z)
many (Zip z) = Zip (map repeat z ++ repeat [])
Tags / Indeces
Interesting. A not completely unrelated thought: ZipLists can be seen as ordinary lists with elements tagged by their (increasing) position index in the list. Zipping application joins two lists by pairing equally-indexed elements.
Imagine lists with elements tagged by (non-decreasing) Ord values. Zippery application would pair-up equally-tagged elements, throwing away all mismatches (it has its uses); zippery alternative could perform order-preserving left-preferring union on tag values (alternative on regular lists is also kind of a union).
This fully agrees with what you propose for indexed lists (aka ZipLists).
So yes, it makes sense.
Streams
One interpretation of a list of values is non-determinacy, which is consistent with the monad instance for lists, but ZipLists can be interpreted as synchronous streams of values which are combined in sequence.
With this stream interpretation it's you don't think in terms of the whole list, so choosing the longest stream is clearly cheating, and the correct interpretation of failing over from the first ZipList to the second in the definition <|> would be to do so on the fly as the first finishes, as you say in your instance.
Zipping two lists together doesn't do this simply because of the type signature, but it's the correct interpretation of <|>.
Longest Possible List
When you zip two lists together, the result is the minimum of the two lengths. This is because that's the longest possible list that meets the type signature without using ⊥. It's a mistake to think of this as picking the shorter of the two lengths - it's the longest possible.
Similarly <|> should generate the longest possible list, and it should prefer the left list. Clearly it should take the whole of the left list and take up the right list where the left left off to preserve synchronisation/zippiness.
Your instance is OK, but it does something ZipList doesn't by
(a) aiming for the longest list, and
(b) mixing elements between source lists.
Zipping as an operation stops at the length of the shortest list.
That's why I concluded in my answer:
Thus the only sensible Alternative instance is:
instance Alternative Zip where
empty = Zip []
Zip [] <|> x = x
Zip xs <|> _ = Zip xs
This is consistent with the Alternative instances for Maybe and parsers that say you should do a if it doesn't fail and go with b if it does. You can say a shorter list is less successful than a longer one, but I don't think you can say a non-empty list is a complete fail.
empty = Zip [] is chosen because it has to be polymorphic in the element type of the list, and the only such list is []
For balance, I don't think your instance is terrible, I think this is cleaner, but hey ho, roll your own as you need it!
There is in fact a sensible Alternative instance for ZipList. It comes from a paper on free near-semirings (which MonadPlus and Alternative are examples of):
instance Alternative ZipList where
empty = ZipList []
ZipList xs <|> ZipList ys = ZipList $ go xs ys where
go [] bs = bs
go as [] = as
go (a:as) (_:bs) = a:go as bs
This is a more performant version of the original code for it, which was
ZipList xs <|> ZipList ys = ZipList $ xs ++ drop (length xs) ys
My guiding intuition for Alternative comes from parsers which suggest that if one branch of your alternative fails somehow it should be eradicated thus leading to a Longest-style Alternative that probably isn't terrifically useful. This would be unbiased (unlike parsers) but fail on infinite lists.
Then again, all they must do, as you suggest, is form a Monoid. Yours is left biased in a way that ZipList doesn't usually embody, though—you could clearly form the reflected version of your Alternative instance just as easily. As you point out, this is the convention with Maybe as well, but I'm not sure there's any reason for ZipList to follow that convention.
There's no sensible some or many I don't believe, although few Alternatives actually have those—perhaps they'd have been better isolated into a subclass of Alternative.
Frankly, I don't think your suggestion is a bad instance to have, but I don't have any confidence about it being "the" alternative instance implied by having a ZipList. Perhaps it'd be best to see where else this kind of "extension" instance could apply (trees?) and write it as a library.