SML Types of rules don't agree and righthand side of clause doesn't agree with function result type - sml

I'm trying to write a function in sml that takes a function and applies it to all elements in a list. If any element returns NONE then the entire function evals to NONE but if any element returns SOME v then that element is added to the accumulator.
The final return value is SOME of the acculumator. Right now I'm getting two errors.
hw4.sml:93.21-95.67 Error: types of rules don't agree [tycon mismatch]
earlier rule(s): 'Z option -> 'Y option
this rule: 'Z option -> 'X list
in rule:
SOME v => ((all_answers_helper ) xs') v # acc
hw4.sml:90.5-95.67 Error: right-hand-side of clause doesn't agree with function result type [tycon mismatch]
expression: 'Z list -> 'Y list -> 'Y list option
result type: 'Z list -> 'Y list -> 'Y list
in declaration:
all_answers_helper = (fn arg => (fn => ))
fun all_answers_helper f xs acc =
case xs of
[] => SOME acc
| x::xs' => case f x of
NONE => NONE
| SOME v => all_answers_helper f xs' v # acc
But I have no idea what I'm doing wrong. All help is appreciated!

It looks like you're getting tripped up by operator precedence. Prefix function and constructor application ("normal ones", like SOME) bind tighter than infix application. So when you write all_answers_helper f xs' v # acc that's the same as (all_answers_helper f xs' v) # acc---the application of all_answers_helper binds tighter than that of #.
You can fix this by doing all_answers_helper f xs' (v # acc) instead. Note that this would imply that v is itself a list. Based on your description of adding "the element" to the accumulator it is possible you instead mean all_answers_helper f xs' (v :: acc), i.e., to just cons the element on instead of appending two lists together.

I think #kopecs has it, but you may also find it useful to make use of pattern matching right in the function signature to make your code easier to reason about.
fun all_answers_helper _ [] acc = SOME acc
| all_answers_helper f (x::xs) acc =
case f x of
NONE => NONE
| SOME v => all_answers_helper f xs (v :: acc)
Understanding operator precedence is crucial to avoid programming errors, but you can also sidestep this by introducing local bindings.
fun all_answers_helper _ [] acc = SOME acc
| all_answers_helper f (x::xs) acc =
case f x of
NONE => NONE
| SOME v =>
let
val updated_acc = v :: acc
in
all_answers_helper f xs updated_acc
end

Related

Position of anonymous function’s parameters in SML’s foldl

I need to write a function that takes a list of strings and finds the largest string in the list. In case of tie, it should return string closest to the end of the list. The catch is it needs to iterate through the list using List.foldl and cannot use recursive calls except for those in the library function of List,foldl.
The following code works fine.
fun longest_string2 str_list =
List.foldl(fn (x, acc) => if String.size x >= String.size acc then x else acc) "” str_list
If I run longest_string2 ["Apple", "ball", "Bpple”]; in REPL, I get val it = "Bpple" : string
However, if I reverse the arguments of anonymous function as below I get val it = "Apple" : string.
Since the anonymous function is accessing the elements by name and not position, why does this makes difference?
The definition of List.foldl is
fun foldl (f: 'a*'b->'b) (acc: 'b) (l: 'a list): 'b =
case l of
[] => acc
| x::xs => foldl f (f(x,acc)) xs
If you reverse arguments of the anonymous function, your function becomes the following: (correct me if I misinterpreted your question)
fun longest_string2 str_list =
List.foldl(fn (acc, x) => if String.size x >= String.size acc then x else acc) "” str_list
If your pass ["Apple", "ball", "Bpple”] as argument to longest_string2 now, the foldl function will pattern match your list with x::xs, where x is “Apple” and xs is ["ball", "Bpple”]. When you compute the updated accumulator using f(x, acc), x and acc gets swapped. In other words, in your anonymous function (with reversed arguments), you would be assuming that the first argument would be ”” and the second argument would be Apple but the implementation of List.foldl will pass f(“Apple”, “”). In this case, your anonymous function will label “Apple” as “acc” and “” as “x”.
#3123 has most answered the question, but has not directly addressed this statement in the question.
Since the anonymous function is accessing the elements by name and not
position, why does this makes difference?
foldl takes a function which takes a tuple as its argument, which is positional.
We could define a fold function which takes a record as its argument instead if we really wanted to achieve this:
fun namedFold _ acc [] = acc
| namedFold f acc (x::xs) =
namedFold f (f {acc=acc, x=x}) xs;
And then call it as:
namedFold (fn { acc, x } => acc + x) 0 [1,2,3,4]
Or as:
namedFold (fn { x, acc } => acc + x) 0 [1,2,3,4]
And get the same result.
But then the type of namedFold is fn :({acc: 'a, x: 'b} -> 'a) -> 'a -> 'b list -> 'a and it becomes essentially impossible to easily pass existing functions to it. With foldl defined the way it is, we can easily rewrite that previous called to namedFold as:
foldl op+ 0 [1,2,3,4]
Because op+ has the same signature as the first argument to foldl.

using filter function to produce a list outputting non-common elements of two lists

So i am in need of a function which takes two lists, x and y and output a list of elements that are in List x BUT NOT IN List y.
ie. the output should look something like is
*Main> filterVars ["a","c","h","d"] ["c","b","a"]
["h","d"]
I want to use the filter function in Haskell to practice. My code is below;
filterVars :: [a] -> [a] -> [a]
filterVars = filter IsInList (y:ys)
where
IsiIList (x:xs) (y:ys) :: [a] -> [a] -> Bool
IsInList [] _ = []
IsiInList(x:xs) (y:ys)
| elem (x (y:ys)) = IsiInList (xs (y:ys))
| otherwise = x : IsiInList (xs (y:ys))
however I get the following error;
Invalid type signature: IsInList (x : xs) (y : ys) :: ...
Should be of form <variable> :: <type>
| IsInList (x:xs) (y:ys) :: [a] -> [a] -> Bool
My logic is as follows:
When the function filterVars is called with arguments (x:xs) (y:ys), it checks to see the filter criteria IsInList.
The function providing the filtering criteria, IsInList, takes both the arguments (x:xs) and (y:ys). if the first element of the list (x:xs) is an elements of (y:ys), then discard and move to the next element in the x list.
For the case that an element of (x:xs) IS NOT IN list (y:ys), store this value and move onto the next element of the list x until list x is completely parsed through.
return the list containing elements of list x that are not in list y
My confusion arises from my lack of experience with Haskell. Firstly the function filterVars must require two lists and output a list. However when i am defining the function, I use the filter function and the list y as arguments. I know filter outputs a list so i just wanted to know if my initial setup is correct (also would like to gain an insight to the flow of execution in Haskell)
Secondly I am not sure as to what the error means and how to resolve it. Does my logic make sense? Can this be done using lists or am i way of mark?
Your code has a few syntactic and semantic errors. I’ll explain the syntax issues and then get into the semantics of your solution.
In Haskell, the names of functions, variables, and type variables must begin with a lowercase letter; capitalised names refer to types, data constructors, or modules. Therefore you need to rename IsInList to isInList, and fix the name typos.
A where clause on a definition is followed by a block of variable bindings (pattern = expression). A block may be delimited by curly braces with items separated by semicolons ({ … ; … ; … }) but it’s more common to use indentation-based layout. Therefore you need to indent the contents of the where block. A simple rule is to put a newline + indent (with spaces) after any layout keyword—where, do, of, or let—whenever you have a multi-line block.
The type signature of a function is written as name :: type, but you’ve written what looks like a pattern on the left-hand side in isInList (x:xs) (y:ys) :: [a] -> [a] -> Bool. If you want to include a type signature here, you should write isInList :: [a] -> [a] -> Bool. However, I’m going to just remove the signature, for reasons I’ll explain below.
With those fixes, your code looks like this:
filterVars :: [a] -> [a] -> [a]
filterVars = filter isInList (y:ys)
where
isInList [] _ = []
isInList (x:xs) (y:ys)
| elem (x (y:ys)) = isInList (xs (y:ys))
| otherwise = x : isInList (xs (y:ys))
Here’s my reading of this code:
filterVars is equal to calling filter with two arguments, isInList and y : ys. y and ys are not in scope here, since you haven’t added them as parameters or pattern variables in the definition of filterVars.
isInList takes two arguments; if the first is an empty list, it returns an empty list. This is not quite right, since filter has the type (a -> Bool) -> [a] -> [a], that is, its first argument should be a function which tests an element of the filtered list and returns a Bool to indicate whether it should be included in the result.
If isInList is given two non-empty lists, then this is followed by a guard to decide which case to proceed to. You’re trying to use the elem function to test whether x is in the list y : ys as the condition here, but the way you call it, you’re passing y : ys as an argument to x, as if it were a function, and then calling elem on the result of that. If you want to pass two arguments to a function, you just separate them with spaces, and include parentheses if necessary for grouping, e.g.: elem x (y : ys). You have the same issue with both calls to isInList (xs (y:ys)), when you probably intended isInList xs (y:ys).
At this point it’s clear to me that you’re mixing up two things: filtering a list using filter, and filtering it by writing a recursive function.
If you want to write this using filter, you should begin with the problem statement: “a function which takes two lists, x and y and output[s] a list of elements that are in List x BUT NOT IN List y”. You want to write a function that takes two parameters, x and y, and filters x by a function that, given an element of x, returns true if the element is not in y.
This can be transcribed fairly literally:
filterVars :: [a] -> [a] -> [a]
-- Select the elements of ‘x’ not in ‘y’…
filterVars x y = filter notInY x
where
-- …where an element ‘e’ is not in ‘y’ if
-- it’s ‘not’ the case that ‘e’ is an ‘elem’ of ‘y’.
notInY e = not (elem e y)
But this has one issue: this function says it can take a list of values of any type a, and test for their presence in a list using elem, but this isn’t true: we could supply a type like Double -> String that’s not comparable at all! In reality, elem is restricted to types that are in the set of types with equality, the Eq typeclass, so we have to add an Eq constraint to the signature to enable the use of elem:
filterVars :: (Eq a) => [a] -> [a] -> [a]
Now, about the local type signature in the where block, the rule in Haskell is that if you write a polymorphic type signature with type variables (typically single letters like a, b, f, m…) then those variables are local to that type signature. So if you write this:
filterVars :: (Eq a) => [a] -> [a] -> [a]
filterVars x y = filter notInY x
where
notInY :: a -> Bool
notInY e = not (elem e y)
That’s equivalent to this:
filterVars :: (Eq a1) => [a1] -> [a1] -> [a1]
filterVars x y = filter notInY x
where
notInY :: a2 -> Bool
notInY e = not (elem e y)
The a of the notInY signature is different from the a in the filterVars signature, so this would cause a type error. The solution is to remove the local type signature or use the ScopedTypeVariables extension to explicitly define the scope of a:
{-# LANGUAGE ScopedTypeVariables #-}
filterVars :: forall a. (Eq a) => [a] -> [a] -> [a]
filterVars x y = filter notInY x
where
notInY :: a -> Bool
notInY e = not (elem e y)
The forall introduces an explicit scope for a, so any a in a type signature in this definition refers to the same a. (An explicit forall is just like the <T> syntax in many imperative programming languages to define generic parameters.)
As a matter of style, you can also write this same structure in a few different ways, and you should make sure you understand these:
filterVars x y = filter (notIn y) x
where
notIn list e = not (elem e list)
filterVars x y = filter (\ e -> not (elem e y)) x
filterVars x y = filter (`notElem` y) x
This is very typical Haskell code, and a good concise solution. But since you’re learning Haskell, you should try to solve this problem with explicit recursion, effectively inlining the definition of filter into your code. For that, you do want to proceed by pattern-matching as you were trying to do in your isInList function. You can start with either of the following structures, using a case expression or multiple function equations, whichever you prefer:
filterVars :: (Eq a) => [a] -> [a] -> [a]
filterVars x y = case x of
[] -> {- 1 -}
e : rest
| {- 2 -} -> {- 3 -}
| otherwise -> {- 4 -}
filterVars :: (Eq a) => [a] -> [a] -> [a]
filterVars [] y = {- 1 -}
filterVars (e : rest) y
| {- 2 -} = {- 3 -}
| otherwise = {- 4 -}
And fill in the following details, marked with {- … -} comments in the code above:
[a]; What do you return when x is empty, i.e., what happens when you call filterVars [] ["c", "b", "a"] directly or as the base case of your recursion?
Bool; When x is non-empty, containing some element e and some (possibly empty) remainder rest, what condition do you use to test whether e is an element of y? (E.g. in filterVars ["a", "d", "b"] ["c", "b", "a"], e is "a" and rest is ["d", "b"].)
[a]; What do you return when e is an element of y? Should you keep or discard the element? What do you do with the rest of the input?
[a]; What do you return when e is not in y? What do you do with the rest of the input then?
Recall that you can always step through Haskell code using equational reasoning, by substituting things on either side of an = sign, since = actually means equal! For example, if your function had a case f [] = [], then whenever you see f [], you can replace it with []; if it had a case f (x : xs) = x + f xs, when you see a call to f [1, 2, 3], this is the same as f (1 : [2, 3]), and likewise f (1 : (2 : (3 : []))), so you can match x = 1 and xs = 2 : (3 : []) and substitute their values in the right-hand side x + f xs → 1 + f [2, 3].

Ocaml Type error: This expression has type 'a * 'b but an expression was expected of type 'c list

I'm required to output a pair of lists and I'm not understanding why the pair I'm returning is not of the correct type.
let rec split l = match l with
| [] -> []
| [y] -> [y]
| x :: xs ->
let rec helper l1 acc = match l1 with
| [] -> []
| x :: xs ->
if ((List.length xs) = ((List.length l) / 2)) then
(xs, (x :: acc))
else helper xs (x :: acc)
in helper l []
(Please take the time to copy/paste and format your code on SO rather than providing a link to an image. It makes it much easier to help, and more useful in the future.)
The first case of the match in your helper function doesn't return a pair. All the cases of a match need to return the same type (of course).
Note that the cases of your outermost match are also of different types (if you assume that helper returns a pair).

Haskell: Is there a left-side identity for the infix (`:`) operator?

In other words, what syntax (if any) could I use in place of XXX in the following implementation of filter:
filter' :: (a -> Bool) -> [a] -> [a]
filter' _ [] = []
filter' f (x:xs) =
let n = if f x then x else XXX
in n:(filter' f xs)
I'm aware of the following alternative implementation (which is recursive and only prepends) but would still be curious if the infix operator has a LHS identity.
filter' :: (a -> Bool) -> [a] -> [a]
filter' _ [] = []
filter' f (x:xs)
| f x = x:(filter' f xs)
| otherwise = filter' f xs
There is none. This can be seen because
ghci> length (undefined : [])
1
so no matter what element you put there, you will always get a length of 1.
How about this phrasing:
filter' f (x:xs) =
let n = if f x then (x:) else id
in n (filter' f xs)
Handwave alert: the following is strictly speaking a lie (because of undefined and such), but it's still a useful idea.
One key property of types defined with Haskell data declarations is that they are free: the set of values for a data type is isomorphic to the set of normal-form terms (fully evaluated expressions) of that type. If two terms of the type are different, then they have different values.
From this it follows that x : xs and xs (in the same scope) must be different lists, simply because they are different terms.
Put a bit differently, the semantics of data types is that if you pattern match on a constructor application you always get back the same constructor and its arguments. For example, these two expressions are guaranteed to be True, no matter what x and xs may be:
case [] of
[] -> True
x:xs -> False
case (x:xs) of
[] -> False
x':xs' -> x == x' && xs == xs'
The left identity value you're looking for would be a counterexample to the second expression here. Ergo, no such value exists.
There is none, but ++ does have an identity, namely []. So this would work as well:
filter' _ [] = []
filter' f (x:xs) =
let n = if f x then [x] else []
in n ++ (filter' f xs)
This is the same as #luqui's answer (as you could prove) only less efficient
, but it keeps things a bit lower-order.

Haskell: return the "list" result of a function as a "list of lists" without using an empty list "[]:foo"

What would be the syntax (if possible at all) for returning the list of lists ([[a]]) but without the use of empty list ([]:[a])?
(similar as the second commented guard (2) below, which is incorrect)
This is a function that works correctly:
-- Split string on every (shouldSplit == true)
splitWith :: (Char -> Bool) -> [Char] -> [[Char]]
splitWith shouldSplit list = filter (not.null) -- would like to get rid of filter
(imp' shouldSplit list)
where
imp' _ [] = [[]]
imp' shouldSplit (x:xs)
| shouldSplit x = []:imp' shouldSplit xs -- (1) this line is adding empty lists
-- | shouldSplit x = [imp' shouldSplit xs] -- (2) if this would be correct, no filter needed
| otherwise = let (z:zs) = imp' shouldSplit xs in (x:z):zs
This is the correct result
Prelude> splitWith (== 'a') "miraaaakojajeja234"
["mir","koj","jej","234"]
However, it must use "filter" to clean up its result, so I would like to get rid of function "filter".
This is the result without the use of filter:
["mir","","","","koj","jej","234"]
If "| shouldSplit x = imp' shouldSplit xs" is used instead the first guard, the result is incorrect:
["mirkojjej234"]
The first guard (1) adds empty list so (I assume) compiler can treat the result as a list of lists ([[a]]).
(I'm not interested in another/different solutions of the function, just the syntax clarification.)
.
.
.
ANSWER:
Answer from Dave4420 led me to the answer, but it was a comment, not an answer so I can't accept it as answer. The solution of the problem was that I'm asking the wrong question. It is not the problem of syntax, but of my algorithm.
There are several answers with another/different solutions that solve the empty list problem, but they are not the answer to my question. However, they expanded my view of ways on how things can be done with basic Haskell syntax, and I thank them for it.
Edit:
splitWith :: (Char -> Bool) -> String -> [String]
splitWith p = go False
where
go _ [] = [[]]
go lastEmpty (x:xs)
| p x = if lastEmpty then go True xs else []:go True xs
| otherwise = let (z:zs) = go False xs in (x:z):zs
This one utilizes pattern matching to complete the task of not producing empty interleaving lists in a single traversal:
splitWith :: Eq a => (a -> Bool) -> [a] -> [[a]]
splitWith f list = case splitWith' f list of
[]:result -> result
result -> result
where
splitWith' _ [] = []
splitWith' f (a:[]) = if f a then [] else [[a]]
splitWith' f (a:b:tail) =
let next = splitWith' f (b : tail)
in if f a
then if a == b
then next
else [] : next
else case next of
[] -> [[a]]
nextHead:nextTail -> (a : nextHead) : nextTail
Running it:
main = do
print $ splitWith (== 'a') "miraaaakojajeja234"
print $ splitWith (== 'a') "mirrraaaakkkojjjajeja234"
print $ splitWith (== 'a') "aaabbbaaa"
Produces:
["mir","koj","jej","234"]
["mirrr","kkkojjj","jej","234"]
["bbb"]
The problem is quite naturally expressed as a fold over the list you're splitting. You need to keep track of two pieces of state - the result list, and the current word that is being built up to append to the result list.
I'd probably write a naive version something like this:
splitWith p xs = word:result
where
(result, word) = foldr func ([], []) xs
func x (result, word) = if p x
then (word:result,[])
else (result, x:word)
Note that this also leaves in the empty lists, because it appends the current word to the result whenever it detects a new element that satisfies the predicate p.
To fix that, just replace the list cons operator (:) with a new operator
(~:) :: [a] -> [[a]] -> [[a]]
that only conses one list to another if the original list is non-empty. The rest of the algorithm is unchanged.
splitWith p xs = word ~: result
where
(result, word) = foldr func ([], []) xs
func x (result, word) = if p x
then (word ~: result, [])
else (result, x:word)
x ~: xs = if null x then xs else x:xs
which does what you want.
I guess I had a similar idea to Chris, I think, even if not as elegant:
splitWith shouldSplit list = imp' list [] []
where
imp' [] accum result = result ++ if null accum then [] else [accum]
imp' (x:xs) accum result
| shouldSplit x =
imp' xs [] (result ++ if null accum
then []
else [accum])
| otherwise = imp' xs (accum ++ [x]) result
This is basically just an alternating application of dropWhile and break, isn't it:
splitWith p xs = g xs
where
g xs = let (a,b) = break p (dropWhile p xs)
in if null a then [] else a : g b
You say you aren't interested in other solutions than yours, but other readers might be. It sure is short and seems clear. As you learn, using basic Prelude functions becomes second nature. :)
As to your code, a little bit reworked in non-essential ways (using short suggestive function names, like p for "predicate" and g for a main worker function), it is
splitWith :: (Char -> Bool) -> [Char] -> [[Char]]
splitWith p list = filter (not.null) (g list)
where
g [] = [[]]
g (x:xs)
| p x = [] : g xs
| otherwise = let (z:zs) = g xs
in (x:z):zs
Also, there's no need to pass the predicate as an argument to the worker (as was also mentioned in the comments). Now it is arguably a bit more readable.
Next, with a minimal change it becomes
splitWith :: (Char -> Bool) -> [Char] -> [[Char]]
splitWith p list = case g list of ([]:r)-> r; x->x
where
g [] = [[]]
g (x:xs)
| p x = case z of []-> r; -- start a new word IF not already
_ -> []:r
| otherwise = (x:z):zs
where -- now z,zs are accessible
r#(z:zs) = g xs -- in both cases
which works as you wanted. The top-level case is removing at most one empty word here, which serves as a separator marker at some point during the inner function's work. Your filter (not.null) is essentially fused into the worker function g here, with the conditional opening1 of a new word (i.e. addition1 of an empty list).
Replacing your let with where allowed for the variables (z etc.) to became accessible in both branches of the second clause of the g definition.
In the end, your algorithm was close enough, and the code could be fixed after all.
1 when thinking "right-to-left". In reality the list is constructed left-to-right, in guarded recursion ⁄ tail recursion modulo cons fashion.