Recursion over lists in Haskell - list

For instance, i have a list like ['a','b','c','d','e'].
I want to do something like this:
First do something with the first two elements, f 'a' 'b'
Then do the same thing with the return value of f and next element in the list, result = f 'a' 'b', lets say like f result 'c'. Then f resultof(result 'c') 'd' and so on.
How can i do something like this?

First let's consider that function f that you have. It takes some sort of accumulated value, a plain value, and combines them into a result. So, in the type signature, we'll say a for the type of the accumulated value, v for the type of the value, and r for the type of the result.
f :: a -> v -> r
Now we want to create a folding function that uses f and a list of values.
someFold :: (a -> v -> r) -> [v] -> ?
What should it return? It should yield something of the resultant type r, right? Notice now that a and r should actually be the same type, since we keep feeding the result of f into it's first argument again.
someFold :: (a -> v -> a) -> [v] -> a
Now one thing's missing. How do you get the very first a? There are two ways to look at that. Either you just pick the first value, in which case a is the same type as v, or you specify a base value, so a could actually be different than v. Let's go with the latter, since that's more interesting. Let's also decide to move left to right in this list. (That's what you need, right?)
someFold :: (a -> v -> a) -> a -> [v] -> a
So...how do we implement it? It'll be recursive, so let's start with the base cases.
someFold f acc [] = acc
If we hit the end of the list, then we've accumulated enough, right? That was easy. So how about the recursive case? From what you said, at each step we should apply f to the "accumulated value so far" as the first argument, and the "first value of the list" as the second. f acc x. Then we keep folding, using that as our new "accumulated" value.
someFold f acc (x:xs) = someFold f (f acc x) xs
Easy, right? But...what if we want to do like you said and start the function by taking the first two values of the list? Also easy. Just take the first element, and call it the original "base" accumulator!
someFold1 :: (v -> v -> v) -> [v] -> v
someFold1 f (x:xs) = someFold f x xs
Notice that since a is the same type as v for this special case, the function someFold1 has a very amusing type signature. If you understood this explanation, then congrats. We've just implemented foldl and foldl1.
Prelude> foldl1 min "abcde" -- "abcde" is sugar for ['a','b','c','d','e']
'a'
In real code, you should actually use foldl' and friends.

Sounds like homework. Take a look at folds.

In this case, the problem with a fold is, that it usually processes on element at a time. You could try to manually roll a fold.
Assume, you have your function f, that gets two elements at a time and the accumulator (the result of the last iteration) fed. Then you function looks like this:
fold2 :: (a -> a -> b -> b) -> [a] -> b -> b
fold2 f accum (x:y:zs) = fold2 f (f x y) zs
fold2 _ accum [] = accum
fold2 _ _ _ = error "odd number of elements"
Try to understand this. fold2 shaves the top two elements of the list of and feeds it into f. The result this is then passed as the new accumulator to the recursive call. This is done until the list is empty.

Related

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

Dealing with unit in Ocaml

So I have a function r which is supposed to apply a function to every element in the list provided it meets a given predicate, and return that list. i.e.
let p x = x > 2;;
let f x = x+1;;
r p f [1;2] => []
I am using a map function that applies a function to every element in a list and then returns that list. Thus my implementation for r is as follows
let r f p l = map f (map (fun x -> if (p x) then x) l );;
but if I attempt to call r like in the example above I get a type error because f and p are expressions for ints and it expected expression for units. Where did I go wrong?
First of all let me explain, why unit comes into play.
In OCaml if/then/else is not a statement, it is an expression, like ternary operator in C-like languages or like conditional expression in Python. Than means, that being an expression it always must have a value. You cannot just give an expression for the true branch, and omit the else branch, unless the value to the else branch is trivial and always known to a compiler. And the latter is only possible for the unit type. Since this type is inhabited with only one value, then if you true branch returns a value of type unit, compiler already knows what would return the false branch. That's why you can omit else part of the expression, that evaluates to unit. And the omission of the else part is satisfactory proof for the compiler that the whole expression has type unit. That means, that in expression if (p x) then x, compiler decided that x has type unit, because there is no else part.
Now to the task. map must return a value for each element of the list. It cannot skip or rearrange, or change the structure. For this there're other higher order functions called filter_map, concat_map, filter, etc.
But lets try to do something without leaving the original wording. So back to your example, we need do something in the else part. What we should return to designate that there is no value? We can return None that is a value of type option, e.g.,
if p x then Some x else None
Notice, that we also need to lift the then part to the option type. As a result we will have a list of type 'a option list. Then we need to filter it, removing Nones.
Other choice is to return an empty list (aka nil), instead of None:
if p x then [x] else []
Then we will have a 'a list list that can be easily transformed to 'a list with concat operation. Moreover, we can notice, that there is no need to create an intermediate list, we can apply f just in place (i.e., there is an opportunity for deforesting optimization here):
if p x then [f x] else []
And finally we have:
let r f p l = concat (map (fun x -> if p x then [f x] else []) l)
Later, you will discover, that both option and list are monads, and this trick with map and concat is actually the core operation for all monads, called bind and denoted as >>=. With this operator defined, we can write r function more elegantly:
let r f p l = l >>= fun x -> if p x then [f x] else []
where the bind operator can be implemented (inefficiently), as
let (>>=) x f = concat (map f x)
But this all was functional mumbo-jumbo, practically, it is better just to use fold_left (as Jeffrey suggested), and accumulate your result in an auxiliary list, without forgetting to reverse it:
let r f p l = rev (fold_left (fun xs x -> if p x then f x :: xs else xs) [] l)
And in real-world programming, you will be using the standard library functions such as List.filter_map or List.concat_map for that.
The map function applies a function to every element of a list and returns the list of results. It always returns a list of equal length to the input list. So your problem statement doesn't make complete sense.
At a lower level, the expression if (p x) then x is only legitimate if x has type unit. I.e., the meaning of if b then e is the same as if b then e else (), and both sides of the if have to be the same type.
If you want to return a list of a different length than your input list, you'll need to use a fold function rather than map.

Haskell - List pattern matching on multiple parameters? (cannot construct the infinite type)

I'm having trouble using list pattern with multiple parameters. For example, trying to define:
somefunction (x:xs) (y:ys) = x:[y]
results in Occurs check: cannot construct the infinite type: t0 = [t0].
Basically, I want to take two lists as parameters to a function and manipulate each of them using the (x:xs) pattern matching approach. Why is this wrong and how can I do it right? Thank you much!
EDIT: Update with more code as suggested was needed in answers.
somefunction a [] = [a]:[]
somefunction [] b = [b]:[]
somefunction (x:xs) (y:ys) = x:[y]
EDIT 2: Missed an important update. The error I'm getting with the above code is Occurs check: cannot construct the infinite type: t0 = [[t0]]. I think I understand the problem now.
Your function snippet is perfectly sound:
(! 514)-> ghci
GHCi, version 7.6.3: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> let f (x:xs) (y:ys) = x:[y]
Prelude> :type f
f :: [a] -> [a] -> [a]
But the context contradicts that type, and the type inference give you that error. For instance, I can create a context that will give this error:
Prelude> let g xs ys = xs : ys
Prelude> :type g
g :: a -> [a] -> [a]
And then if I combine f and g like below, then I get your error:
Prelude> let z x y = g x (f x y)
<interactive>:7:20:
Occurs check: cannot construct the infinite type: a0 = [a0]
In the first argument of `f', namely `x'
In the second argument of `g', namely `(f x y)'
In the expression: g x (f x y)
Prelude>
To understand you error properly, you will need to examine (or post) enough context.
The problem is with all 3 lines taken together:
somefunction a [] = [a]:[]
somefunction [] b = [b]:[]
somefunction (x:xs) (y:ys) = x:[y]
None of them are incorrect taken on their own. The problem is that the three equations are inconsistent about the return type of somefunction.
From the last equation, we can see that both arguments are lists (since you pattern match on them using the list constructor :).
From the last equation, we can see that the return type is a list whose elements must be the same type as the elements of the argument lists (which must also both be the same type), since the return value is x:[y] (which is more often written [x, y]; just the list containing only the two elements x and y) and x and y were elements of the argument lists. So if x has type t0, the arguments to somefunction both have type [t0] and the return type is [t0].
Now try to apply those facts to the first equation. a must be a list. So [a] (the list containing exactly one element a) must be a list of lists. And then [a]:[] (the list whose first element is [a] and whose tail is empty - also written [[a]]) must be a list of lists of lists! If the parameter a has type [t0] (to match the type we figured out from looking at the last equation), then [a] has type [[t0]] and [a]:[] (or [[a]]) has type [[[t0]]], which is the return type we get from this equation.
To reconcile what we learned from those two equations we need to find some type expression to use for t0 such that [t0] = [[[t0]]], which also requires that t0 = [[t0]]. This is impossible, which is what the error message Occurs check: cannot construct the infinite type: t0 = [[t0]] was about.
If your intention was to return one of the parameters as-is when the other one is empty, then you need something more like:
somefunction a [] = a
somefunction [] b = b
somefunction (x:xs) (y:ys) = [x, y]
Or it's possible that the first two equations were correct (you intend to return a list of lists of lists?), in which case the last one needs to be modified. Without knowing what you wanted the function to do, I can't say.
May be you want to write:
somefunction xs [] = xs
somefunction [] ys = ys
somefunction (x:xs) (y:ys) = x : y : []
You have extra brackets. And your definition of x : y not contains []. So compiler think, y is already a list

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