How can I get a value out of a data in Haskell - list

I have the following data:
data LinkedList a = Node a (LinkedList a) | Empty deriving (Show)
And I would like to know how to get a single value out of it, without pattern matching.
So in a C-based language: list.value

Jared Loomis, it sounds like you want to get access to the different parts of your LinkedList with out having to write your own helper functions. So in that light there is an alternative technique of writing data constructors that write these helper functions for you.
data LinkedList a = Node { nodeHead :: a, rest :: LinkedList a} | Empty
deriving (Show)
example usage:
*Main> let example = Node 1 (Node 2 (Node 3 Empty))
*Main> example
Node {nodeHead = 1, rest = Node {nodeHead = 2, rest = Node {nodeHead = 3, rest = Empty}}}
*Main> nodeHead example
1
*Main> nodeHead . rest $ example
2
*Main> nodeHead . rest . rest $ example
3
Careful though nodeHead and rest are considered partial functions and throw an exception when used on Empty:
*Main> nodeHead Empty
*** Exception: No match in record selector nodeHead
*Main> rest Empty
*** Exception: No match in record selector rest
If you want something with post fix syntax I would recommend the
lens package.
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
data LinkedList' a = Node' { _nodeHead' :: a, _rest' :: LinkedList' a} | Empty'
deriving (Show)
makeLenses ''LinkedList'
*Main> example ^? rest'
Just (Node' {_nodeHead' = 2, _rest' = Node' {_nodeHead' = 3, _rest' = Empty'}})
*Main> example ^? rest' . nodeHead'
Just 2

Rather than present a Haskell solution to your question, I will present a more realistic comparison with C and suggest that you don't really want what you seem to be asking for:
struct list {
int value;
struct list *next;
};
int main(void) {
struct list *list = NULL;
int val;
/* Goodbye, cruel world! */
val = list->value;
/* If I had "pattern-matched"... */
if (list == NULL) {
val = 0;
} else {
val = list->value;
}
return 0;
}
When you don't check for the NULL case in C (which corresponds to pattern matching in Haskell) you crash with a SEGFAULT at some point in the execution of your program instead of getting a compile error.
In other words, you can't get a value out of a 'possibly empty' recursive data type without doing case analysis in C either! At least not if you value the stability of your program. Haskell not only insists that you do the right thing, but provides convenient syntax to help you to do so!
As mentioned in other answers, record definition syntax provides you with convenient projections (i.e. accessor functions) automatically, which have a bit of a trade-off in comparison to accessing struct members in C: The projections are first-class, and can thus be used as parameters and return values; but they are in the same namespace as all other functions, which can lead to unfortunate name clashes.
So, in the case of straightforward data types (i.e. non-recursive) the syntax for accessing members is roughly at the same level of convenience: whole.part for C-like languages vs. part whole for Haskell.
For recursive types (like the one in your example) where one or more members reference possibly-empty instances of the same type, case analysis is necessary in either language before a value can be extracted. Here, you will either need to wrap the field access in your C-like language with a case analysis or possibly an exception handler. In Haskell, you have various forms of syntactic sugar for pattern matching that tend to be much more concise.
Furthermore, see the answer regarding Monads for ways of providing even more convenience for working with 'possibly empty' types in Haskell, hiding most of the intermediate pattern matching for multi-step computations inside library functions.
To wrap this up: My point is that as you take the time to learn the patterns and idioms of Haskell, you will likely find yourself missing the ways of doing things in C-like languages less and less.

Let's use monads to do what you'd like. Monads are great because when defining them, you get to redefine what ; and = mean for you. (This being Haskell, we use newlines and indentation to indicate where ; goes and <- to differentiate from the permanent definition =.)
I'll have to use pattern matching to make the instances, because I've got nothing else to go on yet:
instance Monad LinkedList where
Empty >>= f = Empty
(Node a as) >>= f = f a `andthen` (as >>= f)
return a = Node a Empty
The binding operator >>= is the configurable plumbing behind the <- operator. Here we've chosen ; to mean next element, using a helper function addthen in the works:
andthen :: LinkedList a -> LinkedList a -> LinkedList a
Empty `andthen` list = list
(Node a list) `andthen` therest = Node a (list `andthen` therest)
Now we can use monad notation to grab a value at a time. For example, let's apply a function to the elements in a linked list:
applyToElements :: (a -> b) -> LinkedList a -> LinkedList b
applyToElements f list = do
val <- list
return (f val)
ghci> applyToElements ( ++ ", yeah" ) (Node "Hello" (Node "there" Empty))
Node "Hello, yeah" (Node "there, yeah" Empty)
A simpler way
I simply wouldn't have defined that that way. I'd have used pattern matching directly:
applyToElements :: (a -> b) -> LinkedList a -> LinkedList b
applyToElements f Empty = Empty
applyToElements f (Node a list) = Node (f a) (applyToElements f list)
and then declared
instance Functor LinkedList where
fmap = applyToElements
because the usual name for a function that applies another function elementwise is fmap.
More complicated
Monads can be good for other things though, and sometimes it's the best way of expressing something:
combinationsWith :: (a -> b -> c) -> LinkedList a -> LinkedList b -> LinkedList c
combinationsWith f list otherlist = do -- do automatically traverses the structure
val <- list -- works like val = list.value
otherval <- otherlist -- otherval = otherlist.value
return (f val otherval) -- once for each value/othervalue
Because we chose to use andthen when we defined <- for LinkedList, if we use two lists, it'll use the first list and then the second in a sort of nested subloop kind of way, so the otherval values change more frequently than the first vals, so we get:
ghci> combinationsWith (+) (Node 3 (Node 4 Empty)) (Node 10 (Node 100 Empty))
Node 13 (Node 103 (Node 14 (Node 104 Empty)))

As a rule you don't need to extract all values.
If you really wish to extract, use Comonad extract function:
class Functor w => Comonad w where
extract :: w a -> a
...
Often Foldable, Traversable, Monoids, Monad, Zippers are more useful

For the sake of completeness let me mention something I've heard the name "dot hack" for:
Prelude> data LinkedList a = Node { nodeHead :: a, nodeRest :: LinkedList a} | Empty deriving (Show)
Prelude> let example = Node 1 (Node 2 (Node 3 Empty)) :: LinkedList Int
Prelude> let (.) = flip ($)
Prelude> example.nodeRest.nodeHead
2
It's simply realizing that the C-style accessing . is the same as applying accessor functions to the object mentioned before it, which in Haskell means to turn around the arguments of the application operator ($).
Of course, one probably wouldn't use this in real code, since it will cause confusion among other people and the loss of the composition operator.

I'd just pattern match.
llHead :: LinkedList a -> a
llHead Empty = error "kaboom"
llHead (Node x _) = x
If you want the element at a specific index, try something like this (which also uses pattern matching):
llIdx :: LinkedList a -> Int -> a
llIdx l i = go l i
where go Empty _ = error "out of bounds"
go (Node x _) 0 = x
go (Node _ xs) j = go xs (j - 1)
Some assurance that this works:
import Test.QuickCheck
fromList [] = Empty
fromList (x:xs) = Node x (fromList xs)
allIsGood xs i = llIdx (fromList xs) i == xs !! i
llIdxWorksLikeItShould (NonEmpty xs) =
let reasonableIndices = choose (0, length xs - 1) :: Gen Int
in forAll reasonableIndices (allIsGood xs)
-- > quickCheck llIdxWorksLikeItShould
-- +++ OK, passed 100 tests.

Related

Strong union of two lists

I've defined functions:
fun concaten(x,y) =
if (x = [])
then y
else hd(x) :: concaten(tl(x),y);
as well as:
fun existsin(x,L) =
if (L=[])
then false
else if (x = hd(L))
then true
else existsin(x,tl(L));
and am now trying to define a function of type (((list * list) -> list) -> list) that looks vaguely like the following:
fun strongunion(x,y) =
val xy = concaten(x,y);
if xy=[]
then []
if (existsin(hd(xy),tl(xy)) andalso x!= [])
then strongunion(tl(x),y)
else if (existsin(hd(xy),tl(xy)) andalso x = [])
then strongunion(x,tl(y))
else if (x != [])
then hd(xy) :: strongunion(tl(x),y)
else hd(xy) :: strongunion(x,tl(y));
which takes the "strong" union of two lists, i.e. it combats faulty inputs (lists with element duplicates). This code is, of course, syntactically invalid, but the reason I included it was to show what such a function would look like in an imperative language.
The way I started going about doing this was to first concatenate the lists, then remove duplicated elements from that concatenation (well, technically I am adding non-duplicates to an empty list, but these two operations are consequentially equivalent). To do this, I figured I would design the function to take two lists (type list*list), transform them into their concatenation (type list), then do the duplicate removal (type list), which would be of type (((list*list) -> list) -> list).
My issue is that I have no idea how to do this in SML. I'm required to use SML for a class for which I'm a TA, otherwise I wouldn't bother with it, and instead use something like Haskell. If someone can show me how to construct such higher-order functions, I should be able to take care of the rest, but I just haven't come across such constructions in my reading of SML literature.
I'm a bit unsure if strong union means anything other than just union. If you assume that a function union : ''a list * ''a list -> ''a list takes two lists of elements without duplicates as inputs, then you can make it produce the unions without duplicates by conditionally inserting each element from the one list into the other:
(* insert a single element into a list *)
fun insert (x, []) = [x]
| insert (x, xs as (y::ys)) =
if x = y
then xs
else y::insert(x, ys)
(* using manual recursion *)
fun union ([], ys) = ys
| union (x::xs, ys) = union (xs, insert (x, ys))
(* using higher-order list-combinator *)
fun union (xs, ys) = foldl insert ys xs
Trying this:
- val demo = union ([1,2,3,4], [3,4,5,6]);
> val demo = [3, 4, 5, 6, 1, 2] : int list
Note, however, that union wouldn't be a higher-order function, since it doesn't take functions as input or return functions. You could use a slightly stretched definition and make it curried, i.e. union : ''a list -> ''a list -> ''a list, and say that it's higher-order when partially applying it to only one list, e.g. like union [1,2,3]. It wouldn't even be fully polymorphic since it accepts only lists of types that can be compared (e.g. you can't take the union of two sets of functions).

How do you pass list in a function parameter in haskell?

I know this question has been asked previously many times, and I've carefully read them, but it doesn't help me answer my type of question. I'm very new to Haskell,
Lets suppose we have the following:
filter p [] = []
filter p (h:l) = if (p h) then (h:(filter p l)) else (filter p l)
I have two questions
How can I call filter? All I know is that you pass p which is a list
I honestly don't know what is polymorphic type in general, and I cant figure out the polymorphic type of filter function.
I dont event understand what the function filter does in the if statement.
I would really appreciate if you can assist me in these two question.
There's plenty of resources to explain polymorphism, but I don't understand them.
p is not a list. p is short for predicate - usual terminology for a function taking a value and returning Bool. A list is the second argument to filter.
How do you call filter? You need to be reading one of the many haskell books out there. Right now. Some examples:
filter (> 5) [1, 6, 2, 8, 9, 3] -- [6, 8, 9]
filter (== 'z') "bazzz" -- "zzz" (String === [Char])
Here (> 5) :: Int -> Bool and (== 'z') :: Char -> Bool are predicates.
Polymorphic very loosely means it has the same form for different types:
filter :: (a -> Bool) -> [a] -> [a]
filter must work for any type a. The particular a is thus unknown to the implementer and the function cannot assume anything about a. a is chosen by the function user at the call site.
Btw. it's a fun little exercise to figure out what the following function is allowed to do:
:: a -> a
(Hint: there's only one thing it can do, and the name gives it away so I left it out)
You could also think of filter as a family of functions that are implemented exactly the same and only differ in a. Some of those could be:
:: (Int -> Bool) -> [Int] -> [Int]
:: (Char -> Bool) -> [Char] -> [Char]
:: (Foo -> Bool) -> [Foo] -> [Foo]
SO is not really a great place to start when learning new concepts. You should really grab a good book.
Before getting into any details about the implementation, we should settle on what the type of filter should be. Indeed you should generally design the type signature of a function without ever writing any actual code... but the damage is done here already. (As chi remarks, you could at this point actually ask GHCi what the type of your implementation is... but again, that's backwards so I won't delve into it.)
So what do you want filter to accomplish? Indeed it should take a list. You want to extract certain elements of that list depending on some property each of them might have; but filter shouldn't have any hard-baked assumptions what criteria to use, i.e. it should be the type of a list of any type of element. In Haskell, we write this [a] (which is actually shorthand for ∀ a . [a], read this as “for all element-types you might consider – say, A – it's a list of type [A]”).
What the actual criterion is should then be determined by an extra argument: the filtering predicate. For instance, you might want to filter all numbers smaller than 5 from a list of integers – you'd use the predicate (<5) :: Int -> Bool. In general, for your [a] list you need a predicate with the type a -> Bool. The end result would have the same list-elements as you passes in, so then filter would have the signature
filter :: [a] -> (a -> Bool) -> [a]
...except by convention, we put the predicate first, i.e.
filter :: (a -> Bool) -> [a] -> [a]
Let's check this makes sense... we'd want, for instance,
> filter ((<5) :: Int -> Bool) ([4,9,3] :: [Int])
in which case a ~ Int so
filter :: (Int -> Bool) -> [Int] -> [Int]
...yup, that makes sense.
Now you start actually worrying about the implementation. There are two general approaches:
Use some pre-existing combinators from a library to define the function. This is very of preferrable to start dabbling with manual recursion etc., but for now let's do everything by hand.
Deconstruct the list. Basically, there are only two ways a list can look: it can either contain something, or be empty. Empty is easy, because in this case you can't possibly return anything but an empty list again. You can't even use the predicate because there is no element you could check with it, hence just discard it by matching to _:
filter _ [] = []
(Alternatively as you had it, you can also match the predicate as p, but then people will wonder: what happened to the mouse p?)
If the list is not empty, we can straight pop one element from it:
filter p (h:l) = …
here, h is the head element and l is the rest of the list. So great, we now have an element of type a, let's see what the predicate tells us about it!
filter p (h:l) = if p h then … else …
So if the predicate is fulfilled we want to see h again in the final result, won't we? In fact the final result should start with h, thus
filter p (h:l) = if p h then h : … else …
The rest of the final result should have something to do with the rest of the input list. We could pass is as is then h : l else …, but that would mean we would only ever control the condition for the head element. No, we still have to filter the rest of the list as well:
filter p (h:l) = if p h then h : filter p l else …
Indeed we also want to do that even if the predicate is not fulfilled for h, except then we don't prepend it:
filter p (h:l) = if p h then h : filter p l else filter p l
And there you go:
filter _ [] = []
filter p (h:l) = if p h then h : filter p l else filter p l
This if looks a bit clunky, the preferred syntax are actually guards (which do the same thing)
filter _ [] = []
filter p (h:l)
| p h = h : filter p l
| otherwise = filter p l

Getting the head and tail of a custom list type in Haskell

I have a custom list type:
data NNList a = Sing a | Append ( NNList a) ( NNList a) deriving (Eq)
data CList a = Nil | NotNil ( NNList a) deriving (Eq)
I'm trying to implement a function that returns the head and tail of a list:
cListGet :: CList a -> Maybe (a, CList a)
My attempt:
cListGet :: CList a -> Maybe (a, CList a)
cListGet Nil = Nothing
cListGet xs#(NotNil nxs) =
case nxs of
Sing x -> (x, Nil)
Append l r -> ((fst $ cListGet (NotNil l)), (Append (snd $ cListGet (NotNil l)), r))
Which to me means keep going leftwards until I get a single. Once I get the single element (head), return the element and a Nil list. This Nil list is then combined with the list before it's returned as the final result.
I'm not even sure if the logic is 100% correct.
Well, people would normally refer to the data structure you have as a kind of tree, not as a list. But anyway...
Problem #1: Haskell is indentation sensitive, and your case expression is not indented. This leads to a parse error.
Problem #2, and the bigger one: you haven't understood how the Maybe type works yet. I get the impression that you think it works like nulls in more common languages, and this is throwing you off.
In a language like, say, Java, null is a value that can occur where most any other value can. If we have a method with the following signature:
public Foo makeAFoo(Bar someBar)
...then it is legal to call it either of these ways:
// Way #1: pass in an actual value
Bar theBar = getMeABar();
Foo result = makeAFoo(theBar);
// Way #2: pass in a null
Foo result2 = makeAFoo(null)
theBar and null are "parallel" in a sense, or said more precisely, they have the same type—you can replace one with the other in a program and it will compile in both cases.
In Haskell, on the other hand, the string "hello" and Nothing do not have the same type, and you cannot use one where the other goes. Haskell distinguishes between these three things:
A string that's required to be there: "hello" :: String
The absence of an optional string: Nothing :: Maybe String
The presence of an optional string: Just "hello" :: Maybe String
The difference between #1 and #3 is what you're systematically missing in your function. With Maybe a, in the cases where you do have a value you must use Just, which acts like a wrapper to signify "this isn't just an a, it's a Maybe a."
First place you're missing Just is the right hand sides of the case expressions, which we can fix like this:
-- This still fails to compile!
cListGet :: CList a -> Maybe (a, CList a)
cListGet Nil = Nothing
cListGet xs#(NotNil nxs) =
case nxs of
-- I added 'Just' here and in the next line:
Sing x -> Just (x, Nil)
Append l r -> Just (fst $ cListGet (NotNil l), (Append (snd $ cListGet (NotNil l)), r))
But this isn't the end of it, because you're doing fst $ cListGet (NotNil l), which suffers from the converse problem: cListGet returns Maybe (a, CList a), but fst works on (a, b), not on Maybe (a, b). You need to pattern match on the result of cListGet to test whether it's Nothing or Just (x, l'). (This same problem occurs also in your snd $ cListGet (NotNil l).)
Third, you're using your Append constructor wrong. You have it in the form of (Append foo, bar), which should have no comma between foo and bar. In Haskell this sort of thing will give you more confusing error messages than most other languages, because when Haskell sees this, it doesn't tell you "you made a syntax error"; Haskell is rather more literal than most languages, so it figures you're trying to make a pair with Append foo as the first element, and bar as the second one, so it concludes that (Append foo, bar) must have type (NNList a -> NNList a, NNList a).
The fourth and final problem: the problem you've set yourself is not clearly stated, and thus has no good answer. You say you want to find the "head" and "tail" of a CList a. What does that mean? In the case of the Haskell [a] type, with constructors [] and :, this is clear: the head is the x in x:xs, and the tail is the xs.
As I understand you, what you mean by "head" seems to be the leftmost element of the recursive structure. We could get that this way:
cListHead :: CList a -> Maybe a
cListHead Nil = Nothing
-- No need to cram everything together into one definition; deal with
-- the NNList case in an auxiliary function, it's easier...
cListGet (NotNil nxs) = Just (nnListHead nxs)
-- Note how much easier this function is to write, because since 'NNList'
-- doesn't have a 'Nil' case, there's no need to mess around with 'Maybe'
-- here. Basically, by splitting the problem into two functions, only
-- 'cListHead' needs to care about 'Maybe' and 'Just'.
nnListHead :: NNList a -> a
nnListHead (Sing a) = a
nnListHead (Append l _) = nnListHead l
So you might think that "the tail" is everything else. Well, the problem is that "everything else" is not a subpart of your CList or NNList. Take this example:
example :: CList Int
example = NotNil (Append (Append (Sing 1) (Sing 2)) (Sing 3))
The "head" is 1. But there is no subpart of the structure defined in example that contains 2 and 3 without containing 1 as well. You'd have to construct a new CList with a different shape than the original to get that. That's possible to do, but I don't see the value of it as a beginner's exercise, frankly.
In case it's not clear what I mean by a "subpart," think of the example as a tree:
NotNil
|
v
Append
/ \
v v
Sing Append
| / \
v v v
1 Sing Sing
| |
v v
2 3
Subpart = subtree.
Hint: try to rewrite this using only pattern matching and not equality-checking (==).
Edit:
First off, it's crucial that you understand what pattern matching is and how it works. I'd recommend going here and reading up; there are also plenty of other resources about this on the web (Google is your friend).
Once you've done that, here's another hint: First write a function nnListGet :: NNList a -> (a, CList a), then use it to implement cListGet.
Just to add to the other (very thorough) answers: It's good to realize that your custom list is a foldable structure. This means, it represents a sequence of values that can be combined together. Such datatypes can implement Foldable type class. In your case, it would be:
import Prelude hiding (foldr)
import Data.Foldable
data NNList a = Sing a | Append (NNList a) (NNList a) deriving (Eq)
data CList a = Nil | NotNil (NNList a) deriving (Eq)
instance Foldable NNList where
foldr f z (Sing x) = f x z
foldr f z (Append xs ys) = foldr f (foldr f z ys) xs
instance Foldable CList where
foldr _ z Nil = z
foldr f z (NotNil xs) = foldr f z xs
From that you'll get all functions defined in Data.Foldable for free, such as maximum/minimum, searching for an element etc.
For any Foldable, you can implement headMaybe that returns its first element by using First monoid. It's a very simple monoid that returns the left-most non-empty element. So if you fold all elements of a Foldable using this monoid, you'll get its first one:
import Data.Monoid
headMaybe :: (Foldable f) => f a -> Maybe a
headMaybe = getFirst . foldMap (First . Just)
(Alternatively, you can use foldr directly, using Maybe's instance of Alternative, which again returns the left-most non-empty element:
import Control.Applicative
headMaybe = foldr (\x y -> pure x <|> y) Nothing
.)
However, this doesn't solve the second part of your question - computing tailMaybe. This can't be defined in a generic way like headMaybe, and you'll need your custom function for that, as you did.
See also:
Fold on Wikipedia.
Foldable and Traversable on Haskell wiki.
Fold on Haskell wiki.
List processing on Haskell wikibook.
Why did you declare that in terms of two types? Here's a seemingly more appropriate type declaration with a correct function:
data CList a
= Nil
| Sing a
| Append (CList a) (CList a)
deriving (Eq)
headAndTail :: CList a -> Maybe (a, CList a)
headAndTail Nil = Nothing
headAndTail (Sing a) = Just (a, Nil)
headAndTail (Append a b) =
case headAndTail a of
Nothing -> headAndTail b
Just (head, tail) -> Just (head, Append tail b)

SML: How can I pass a function a list and return the list with all negative reals removed?

Here's what I've got so far...
fun positive l1 = positive(l1,[],[])
| positive (l1, p, n) =
if hd(l1) < 0
then positive(tl(l1), p, n # [hd(l1])
else if hd(l1) >= 0
then positive(tl(l1), p # [hd(l1)], n)
else if null (h1(l1))
then p
Yes, this is for my educational purposes. I'm taking an ML class in college and we had to write a program that would return the biggest integer in a list and I want to go above and beyond that to see if I can remove the positives from it as well.
Also, if possible, can anyone point me to a decent ML book or primer? Our class text doesn't explain things well at all.
You fail to mention that your code doesn't type.
Your first function clause just has the variable l1, which is used in the recursive. However here it is used as the first element of the triple, which is given as the argument. This doesn't really go hand in hand with the Hindley–Milner type system that SML uses. This is perhaps better seen by the following informal thoughts:
Lets start by assuming that l1 has the type 'a, and thus the function must take arguments of that type and return something unknown 'a -> .... However on the right hand side you create an argument (l1, [], []) which must have the type 'a * 'b list * 'c list. But since it is passed as an argument to the function, that must also mean that 'a is equal to 'a * 'b list * 'c list, which clearly is not the case.
Clearly this was not your original intent. It seems that your intent was to have a function that takes an list as argument, and then at the same time have a recursive helper function, which takes two extra accumulation arguments, namely a list of positive and negative numbers in the original list.
To do this, you at least need to give your helper function another name, such that its definition won't rebind the definition of the original function.
Then you have some options, as to which scope this helper function should be in. In general if it doesn't make any sense to be calling this helper function other than from the "main" function, then it should not be places in a scope outside the "main" function. This can be done using a let binding like this:
fun positive xs =
let
fun positive' ys p n = ...
in
positive' xs [] []
end
This way the helper function positives' can't be called outside of the positive function.
With this take care of there are some more issues with your original code.
Since you are only returning the list of positive integers, there is no need to keep track of the
negative ones.
You should be using pattern matching to decompose the list elements. This way you eliminate the
use of taking the head and tail of the list, and also the need to verify whether there actually is
a head and tail in the list.
fun foo [] = ... (* input list is empty *)
| foo (x::xs) = ... (* x is now the head, and xs is the tail *)
You should not use the append operator (#), whenever you can avoid it (which you always can).
The problem is that it has a terrible running time when you have a huge list on the left hand
side and a small list on the right hand side (which is often the case for the right hand side, as
it is mostly used to append a single element). Thus it should in general be considered bad
practice to use it.
However there exists a very simple solution to this, which is to always concatenate the element
in front of the list (constructing the list in reverse order), and then just reversing the list
when returning it as the last thing (making it in expected order):
fun foo [] acc = rev acc
| foo (x::xs) acc = foo xs (x::acc)
Given these small notes, we end up with a function that looks something like this
fun positive xs =
let
fun positive' [] p = rev p
| positive' (y::ys) p =
if y < 0 then
positive' ys p
else
positive' ys (y :: p)
in
positive' xs []
end
Have you learned about List.filter? It might be appropriate here - it takes a function (which is a predicate) of type 'a -> bool and a list of type 'a list, and returns a list consisting of only the elements for which the predicate evaluates to true. For example:
List.filter (fn x => Real.>= (x, 0.0)) [1.0, 4.5, ~3.4, 42.0, ~9.0]
Your existing code won't work because you're comparing to integers using the intversion of <. The code hd(l1) < 0 will work over a list of int, not a list of real. Numeric literals are not automatically coerced by Standard ML. One must explicitly write 0.0, and use Real.< (hd(l1), 0.0) for your test.
If you don't want to use filter from the standard library, you could consider how one might implement filter yourself. Here's one way:
fun filter f [] = []
| filter f (h::t) =
if f h
then h :: filter f t
else filter f t

Lazy vs eager evaluation and double linked list building

I can't sleep! :)
I've written small program building double linked list in Haskell. The basic language's property to make it was lazy evaluation (see the bunch of code below). And my question is can I do the same in a pure functional language with eager evaluation or not? In any case, what properties eager functional language must have to be able to build such structure (impurity?)?
import Data.List
data DLList a = DLNull |
DLNode { prev :: DLList a
, x :: a
, next :: DLList a
}
deriving (Show)
walkDLList :: (DLList a -> DLList a) -> DLList a -> [a]
walkDLList _ DLNull = []
walkDLList f n#(DLNode _ x _) = x : walkDLList f (f n)
-- Returns first and last items.
makeDLList :: [a] -> (DLList a, DLList a)
makeDLList xs = let (first, last) = step DLNull xs in (first, last)
where
step prev [] = (DLNull, prev)
-- Here I use laziness. 'next' is not built yet, it's a thunk.
step prev (x : xs) = let this = DLNode prev x next
(next, last) = step this xs
in (this, last)
testList :: [Int] -> IO ()
testList l = let
(first, last) = makeDLList l
byNext = walkDLList next first
byPrev = walkDLList prev last
in do
putStrLn $ "Testing: " ++ show l
print byNext
print byPrev
main = do
testList []
testList [1, 2, 3, 4]
A doubly-linked list can be implemented in a purely functional way in an eager language as a zipper on a singly-linked list. See, for example, Rosetta Code > Doubly-linked list > OCaml > Functional.
As long as a language has something like closures, lambdas etc. you can always simulate lazyness. You could rewrite that code even in Java (without mutating variables etc), you just need to wrap every "lazy" operation in something like
interface Thunk<A> {
A eval();
}
Of course this would look terrible, but it is possible.
In the non-backtracking subset of Prolog, which can be seen as explicitly set-once eager pure functional language, you can build the doubly-linked lists easily. It's the referential transparency that makes it hard in Haskell, for it forbids the Prolog's explicit setting of the named, explicitly not-yet-set logical variables, and instead forces Haskell to achieve same effect in the warped way of "tying the knot". I think.
Plus, there really isn't much difference between Haskell's guarded recursion under lazy evaluation vs. Prolog's open-ended lists built in tail-recursion modulo cons fashion. IMO. Here's for instance an example of lazy lists in Prolog. The memoized shared storage is used as universal access mediator, so the results of previous calculations can be arranged to be cached.
Come to think of it, you can use C in a restrictive manner as an eager pure functional language, if you never reset any variable nor any pointer once it is set. You still have null pointers, just as Prolog has variables, so it is too, explicitly set-once. And of course you can build doubly-linked lists with it.
So the only question that remains is, do you admit such set-once languages as pure?