foldl function in SML/NJ: Right-hand-side of clause doesn't agree with function result type - sml

I have a function named dfs which produces a list of all visited nodes in a graph represented by a list of tuples such as [(node1,node2,weight),....] and I get this error :
v.sml:72.7-79.16 Error: right-hand-side of clause doesn't agree with function result type [circularity]
expression: ''Z -> ''Z list
result type: ''Z list -> ''Z list
in declaration:
find_visited = (fn arg => (fn <pat> => <exp>))
uncaught exception Error
raised at: ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
../compiler/TopLevel/interact/evalloop.sml:44.55
../compiler/TopLevel/interact/evalloop.sml:292.17-292.20
-
Code :
fun succesors n e =
List.map (fn (_, v, _) => v) (List.filter (fn (u, _, _) => n = u) e)
fun dfs graph start =
let
fun find_visited visited node =
if not (List.exists (fn x => x = node) visited) then
let
val s = (succesors node graph)
in
foldl (fn (v, n) => (find_visited v n)) (node::visited) s
end
else
visited
in
find_visited [] start
end

foldl has the type ('a * 'b -> 'b) -> 'b -> 'a list -> 'b.
That is, the function to fold is list_element * result -> result, and (fn (v, n) => ... should be (fn (n, v) => ...
(This is the opposite order to OCaml's fold_left.)

Related

Standard ML :How to cycle through a list?

I am trying to write a program that cycle through a list n times.
Suppose that L = [a1, a2, ... , an]
What I am trying to achieve is [ai+1, a i+2, ... , an, a1, a2, ... , ai].
I referenced to a previous post about this exact problem. However, I am not sure how to obtain the output or [ai+1, a i+2, ... , an, a1, a2, ... , ai].
For the output: I tried
-cycle([1,2,3,4], 5);
However the error that I am getting is that the operand and operator don't match
This is the code I found from the previous post:
fun cycle n i =
if i = 0 then n
else cycle (tl n) (i-1) # [hd(n)];
A way to do this using if-then-else:
fun cycle xs n =
if n = 0
then []
else xs # cycle xs (n - 1)
You might instead like to use pattern matching:
fun cycle xs 0 = []
| cycle xs n = xs # cycle xs (n - 1)
But the most elegant solution, I think, is using higher-order functions:
fun cycle xs n =
List.concat (List.tabulate (n, fn _ => xs))
A slightly harder task is how to write a cycle for lazy lists that cycles infinitely...
datatype 'a lazylist = Cons of 'a * (unit -> 'a lazylist) | Nil
fun fromList [] = Nil
| fromList (x::xs) = Cons (x, fn () => fromList xs)
fun take 0 _ = []
| take _ Nil = []
| take n (Cons (x, tail)) = x :: take (n - 1) (tail ())
local
fun append' (Nil, ys) = ys
| append' (Cons (x, xtail), ys) =
Cons (x, fn () => append' (xtail (), ys))
in
fun append (xs, Nil) = xs
| append (xs, ys) = append' (xs, ys)
end
fun cycle xs = ...
where take 5 (cycle (fromList [1,2])) = [1,2,1,2,1].

predicate and a list search haskell

I am learning Haskell at the moment and have come to a bit of a standstill. I'm trying to write a function that takes a predicate p and a list xs and returns the list of those elements of xs which immediately follow an element which passes the predicate p. Here is what I have :
afterFilter :: (a -> Bool) -> [a] -> [a]
afterFilter x (y:ys) =
if x y
then (map head [ys])
else
afterFilter x (tail ys)
test input : afterFilter (<0) [-4,7,-4,-8,3,-3,-6,0,-9,-1]
output : [7]
The trick is to pull two elements out of the input list by pattern-matching two cons cells. If the first element passes the predicate, we stick the second on the output. But don't forget to stick the second element back on the input list when you make the recursive call.
afterFilter :: (a -> Bool) -> [a] -> [a]
afterFilter f [] = [] -- input list is empty
afterFilter f [x] = [] -- input list has only one element - no "next element" to return
afterFilter f (x:y:xs) =
let ys = afterFilter f (y:xs)
in (if f x then y:ys else rest)
However, a higher-level - and much more Haskellish - way to approach the problem would be to break it down into a pipeline of operations.
Pair up each item in the list with the element that follows it using zip, so we have a list of (element, next) pairs.
Use filter to drop the pairs for which element does not pass the predicate.
Use map to extract the next part of each surviving pair.
So the code looks like this:
pairWithSuccessors :: [a] -> [(a, a)]
pairWithSuccessors xs = zip xs (tail xs)
afterFilter :: (a -> Bool) -> [a] -> [a]
afterFilter p xs =
let withSuccessors = pairWithSuccessors xs (tail xs)
filtered = filter (\(element, next) -> p element) withSuccessors
filteredSuccessors = map (\(element, next) -> next) filtered
in filteredSuccessors
Or, written in point-free style:
afterFilter p = map snd . filter (p . fst) . pairWithSuccessors
Functions built with the composition operator . are read right-to-left: first pairWithSuccessors, then filter (p . fst), then map snd over the result.
GHC is good at working with lists: when compiled with optimisations, both approaches should produce roughly the same machine code - that is, there's no performance cost to the high-level solution
Following what you did, there are some strange things with your code :
The map head [ys] is very odd, and causes your function to stop : At the first element matching the predicate, your function returns a list containing its immediate successor and stops there. You still need to process the rest of the list.
Also, following your definition of the problem, each item which is a successor of an item passing the predicate should be on the resulting array. I may be wrong, but what I understood is that afterFilter (<0) [-1, -1, 1] should return [-1, 1].
However, you're discarding one element you didn't check for by calling tail ys : You checked for y, but not for head ys.
Finally, by adding the edge cases, here is what you get :
afterFilter :: (a -> Bool) -> [a] -> [a]
afterFilter _ [] = []
afterFilter _ [_] = []
afterFilter x (y:ys#(z:zs)) =
if x y
then z : afterFilter x ys
else
afterFilter x ys
Try:
afterFilter :: (a -> Bool) -> [a] -> [a]
afterFilter p [] = []
afterFilter p [_] = []
afterFilter p (x1:x2:xs)
| p x1 = x2:rest
| otherwise = rest
where rest = afterFilter p (x2:xs)
Or
afterFilter' :: (a -> Bool) -> [a] -> [a]
afterFilter' p xs = map snd $ filter (\(x, _) -> p x) $ zip xs (tail xs)
Or
afterFilter'' :: (a -> Bool) -> [a] -> [a]
afterFilter'' p xs = [y | (x, y) <- zip xs (tail xs), p x]

data List - checking if a list is empty

I have the following. It just simply checks if a List is empty. However if I try to run it with main, I get an error. How do I need to change the main function to run it properly?
data List a = Nil | Cons a (List a)
vnull :: List a -> Bool
vnull Nil = True
vnull _ = False
main = do print (vnull [1,2])
The error is the following:
Couldn't match expected type `List a0' with actual type `[Integer]'
In the first argument of `vnull', namely `[1, 2]'
In the first argument of `print', namely `(vnull [1, 2])'
In a stmt of a 'do' block: print (vnull [1, 2])
Changing to:
main = print $ vnull $ Cons 1 $ Cons 2 Nil
produces:
False
If you want to be able to use your List type with the usual list syntax, you'll have to use GHC extensions.
{-# LANGUAGE OverloadedLists, TypeFamilies #-} -- at the very top of the file
import qualified GHC.Exts as E
import Data.Foldable
data List a = Nil | Cons a (List a) deriving (Show, Eq, Ord)
instance Foldable List where
foldr _ n Nil = n
foldr c n (Cons x xs) = x `c` foldr c n xs
instance E.IsList List where
type Item (List a) = a
fromList = foldr Cons Nil
toList = toList
it is working like it is implemented:
vnull Nil
True
vnull (Cons 1 Nil)
False
vnull (Cons 2 (Cons 1 Nil)
False
...
you can try following commands in ghci, to get all information about [] datatype:
Prelude> :t []
[] :: [t]
Prelude> :i []
data [] a = [] | a : [a] -- Defined in ‘GHC.Types’
instance Eq a => Eq [a] -- Defined in ‘GHC.Classes’
instance Monad [] -- Defined in ‘GHC.Base’
instance Functor [] -- Defined in ‘GHC.Base’
instance Ord a => Ord [a] -- Defined in ‘GHC.Classes’
instance Read a => Read [a] -- Defined in ‘GHC.Read’
instance Show a => Show [a] -- Defined in ‘GHC.Show’
instance Applicative [] -- Defined in ‘GHC.Base’
instance Foldable [] -- Defined in ‘Data.Foldable’
instance Traversable [] -- Defined in ‘Data.Traversable’
instance Monoid [a] -- Defined in ‘GHC.Base’
for your function to be applicable to [] parameter you need something like:
vnull :: [a] -> Bool
vnull [] = True
vnull _ = False
This is what you are missing:
data List a = Nil | Cons a (List a) deriving Show
fromList = foldr Cons Nil
vnull :: List a -> Bool
vnull Nil = True
vnull _ = False
main = do print (vnull $ fromList [1,2])
The deriving Show is not necessary now, but will be, when you actually want to print a List and not a Bool. The fromList function does nothing, but to convert the Haskell Listimplementation (here [1,2]) into your own, so you can call vnull on it. You could have also called
main = do print $ vnull (Cons 1 (Cons 2 (Nil)))
List a
and
[]
Are two different constructors and not the same data type, The function would work for a List a type, so instead of "[]" try this:
vnull :: List a -> Bool
vnull Nil = True
vnull (Cons a expand) = False
Then in main
main = do print (vnull $ Cons 1 (Cons 2 Nil)) --This is just an example you can throw in a -List a- type of any length.
And this should fix it.
You can:
instance Foldeable List where
foldMap f Nil = mempty
foldMap f (Cons x ls) = mappend (f x) (foldMap ls)
Then use (fold [1,2])::List Int

Haskell 99 Problems #7: Prepend vs Append to List

This passes:
data Nested List a = Elem a | List [NestedList a]
flatten :: NestedList a -> [a]
flatten (Elem a) = [a]
flatten (List (x:xs)) = flatten x ++ flatten (List xs)
flatten (List []) = []
This fails:
data NestedList a = Elem a | List [NestedList a]
flatten :: NestedList a -> [a]
flatten (Elem a) = [a]
flatten (List (x:xs)) = flatten x : flatten (List xs)
flatten (List []) = []
Error is:
Couldn't match expected type `a' with actual type `[a]'
`a' is a rigid type variable bound by
the type signature for flatten :: NestedList a -> [a]
at 007.hs:2:12
Relevant bindings include
xs :: [NestedList a] (bound at 007.hs:4:18)
x :: NestedList a (bound at 007.hs:4:16)
flatten :: NestedList a -> [a] (bound at 007.hs:3:1)
In the first argument of `(:)', namely `flatten x'
In the expression: flatten x : flatten (List xs)
The difference is ++ instead of :. I know the former appends, the latter prepends, but why doesn't : work in this case? I don't understand the error.
Actually ++ is the concatenation operator, which expects both the operators to be a list in this particular case. Since flatten returns a list, ++ concatenates them happily.
But, : just prepends only one item to a list. Since flatten x in flatten x : flatten (List xs) returns a list, : throws this error.

foldl operation in sml

I would appreciate if someone could guide me here, I really want to understand what I did wrong and why?
This is my code:
fun get_longest xs = foldl((fn (x ,y ) => if String.size x >= String.size y then x
else y),[],xs)
My function should take a list of strings and return the longest string; if the list is empty, just return [].
But I'm getting this error:
Error: operator and operand don't agree [tycon mismatch]
operator domain: 'Z * 'Y -> 'Y
operand: (string * string -> string) * int * 'X
in expression:
foldl ((fn (<pat>,<pat>) => if <exp> then <exp> else <exp>),0,xs)
uncaught exception Error
raised at: ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
../compiler/TopLevel/interact/evalloop.sml:44.55
../compiler/TopLevel/interact/evalloop.sml:296.17-296.20
Take a look at the signature of foldl:
val foldl : ('a * 'b -> 'b) -> 'b -> 'a list -> 'b
You can see that your function should have the form
fun get_longest xs = foldl foo acc xs
where foo is the function applies on an element and an accumulator and acc is the initial accumulator.
Hints:
Since get_longest returns a string, the accumulator should have type string. Your job is to find out a suitable string to fill in. Note that the value [] you want here doesn't make sense.
xs is a string list, your foo function should have type string * string -> string. Now you have to replace foo by an appropriate anonymous function.
foldl is a curried functions, it's type is ('a * 'b -> 'b) -> 'b -> 'a list -> 'b. Therefore it should be called as foldl f s xs. You're calling it as foldl (f, s, xs). That's wrong because it calls foldl with a tuple as its argument and foldl does not expect a tuple. If it did, its type would be ('a * 'b -> 'b) * 'b * 'a list -> 'b.