Write an ML High-order function philter(f,x,L) that takes a function f and an element x and returns the list of all those elements y on list L such that f(x,y) = true.
Philter:((a’ * a’)→bool * a’ * a’list)→a’list
My code
fun filter p [] = [] | filter p (x::xs) =
if p x
then
x :: filter p xs
else
filter p xs;
filter (fn(x) => x<6) [6,3,0,1,8,5,9,3]; filter (fn(x) => x<6)
and i have diffrent val filter = fn : ('a -> bool) -> 'a list -> 'a list
any one can help me ?
Your function only takes a list and a function as argument where is the third argument e.g element x ??
As a consequence you check the condition p x and not p(x,y), from your description p should have type:
(a'* a') -> bool
Here is my implementation:
fun filter (p :('a * 'a -> bool) , _ ,[]) = []
| filter (p, x ,(y::ys))= if p (x,y) then y :: filter (p, x, ys)
else filter (p, x, ys);
and here is a tail-recursive implementation:
fun filter2 (p : ('a * 'a -> bool), x, L)=
let
fun filter3 (p, _, [], L) = rev L
| filter3 (p, x, (y::ys), L) = if p (x,y) then filter3 (p, x, ys, (y::L))
else filter3 (p, x, ys, L);
in
filter3 (p, x, L, [])
end
Example (see types and results):
val filter = fn : ('a * 'a -> bool) * 'a * 'a list -> 'a list
val filter2 = fn : ('a * 'a -> bool) * 'a * 'a list -> 'a list
val it = () : unit
- filter ((fn(x,y) => x<y), 4,[6,3,0,1,8,5,9,3]);
val it = [6,8,5,9] : int list
- filter2 ((fn(x,y) => x<y), 4,[6,3,0,1,8,5,9,3]);
val it = [6,8,5,9] : int list
By relying on the built-in List.filter, your philter could look like:
fun philter (f, x, L) = List.filter (fn y => f (x, y)) L
Related
This is a homework. I know I shouldn't ask this here but explanation would be welcomed. :)
My code looks like that:
let some_function f x = match x with
| (k, v) -> fun k -> f k
f should be a function and x is a list of tuples.
My compiler (?) says it's
('a -> 'b) -> 'c * 'd -> 'a -> 'b but it should be ('a -> 'b) -> 'a * 'b -> 'a -> 'b
You don't need to tell me the solution just explain me why it's 'c * 'd and not 'a * 'b
First off, when you write this:
let some_function f x = match x with
| (k, v) -> fun k -> f k
You can pattern match directly in the function arguments.
let some_function f (k, v) =
fun k -> f k
Secondly, the v is never used, so let's get red of that by using _.
let some_function f (k, _) =
fun k -> f k
This does exactly the same thing and gives us something easier to reason about.
However, the k in fun k -> f k shadows the k in the tuple argument to the function, so you're not really using that one either.
So we really have:
let some_function f (_, _) =
fun k -> f k
The concrete types of these are not known, so f is inferred to be a function that takes a value of type 'a and returns a value of type 'b. Therefore f is 'a -> 'b.
That tuple that you never use? It has a type, but we can't know anything about those types from the rest of the function, so the inferred type is 'c * 'd.
We can simplify this one step further. fun k -> f k is equivalent to just writing f, so your function can be equivalently rewritten:
let some_function f (_, _) = f
Though this doesn't allow OCaml to infer that f is a function, so the type signature becomes:
'a -> 'b * 'c -> 'a
I was wondering how to write my own sortOn function.
I made a sortBy function and an on function as shown bellow but can't figure out how to combine them and what additional code to add. sortOn is like sortBy but the given function (in here named comp) is applied only once for every element of the list
sortBy :: (a -> a -> Ordering) -> [a] -> [a]
sortBy comp [] = []
sortBy comp [x] = [x]
sortBy comp (x:xs) = insert x (sortBy comp xs)
where
insert x [] = [x]
insert x (y:ys)
| (comp x y == LT) || (comp x y == EQ) = x:y:ys
| otherwise = y:(insert x ys)
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
on b f x y = b (f x) (f y)
Here's a hint.
If you have a list [a] and you just sort it, the sort function will implicitly make use of the Ord instance for a and specifically the function:
compare :: a -> a -> Ordering
to figure out the relative ordering of pairs of a elements.
Now, if you have a list [a] and a transformation function b, and you want to use sortOn to sort the list of the transformed values, you'll need to figure out the relative ordering of pairs of b elements. How will you do this? Well, you'll implicitly use the Ord instance for b and specifically the function:
compare :: b -> b -> Ordering
In other words, when you try to define:
sortOn :: (Ord b) => (a -> b) -> [a] -> [a]
sortOn f lst = ...
you'll have arguments of type:
f :: a -> b
lst :: [a]
and additional objects of type:
sortBy :: (a -> a -> Ordering) -> [a] -> [a]
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
compare :: b -> b -> Ordering
Now, can you see how to put them together to define sortOn?
SPOILERS
Further hint: What's the type of compare `on` f?
Further further hint: It's a -> a -> Ordering.
I am currently taking a class in Haskell and am having a bit of trouble understanding how functions are passed as parameters. For this assignment, we were tasked with creating a program that would evaluate expressions. To reduce boiler plating, I wanted to abstract the function by creating a helper function that would take in an operator as an input and return the result
Main Function:
eval :: EDict -> Expr -> Maybe Double
eval _ (Val x) = Just x
eval d (Var i) = find d i
eval d (Add x y) = evalOp d (+) x y
eval d (Mul x y) = evalOp d (*) x y
eval d (Sub x y) = evalOp d (-) x y
Helper Function:
evalOp:: EDict -> ((Num a) => a -> a -> a) -> Expr -> Expr -> Maybe Double
evalOp d op x y =
let r = eval d x
s = eval d y
in case (r, s) of
(Just m, Just n) -> Just (m `op` n)
_ -> Nothing
Other definitions
data Expr
= Val Double
| Add Expr Expr
| Mul Expr Expr
| Sub Expr Expr
| Dvd Expr Expr
| Var Id
| Def Id Expr Expr
deriving (Eq, Show)
type Dict k d = [(k,d)]
define :: Dict k d -> k -> d -> Dict k d
define d s v = (s,v):d
find :: Eq k => Dict k d -> k -> Maybe d
find [] _ = Nothing
find ( (s,v) : ds ) name | name == s = Just v
| otherwise = find ds name
type EDict = Dict String Double
I looked into how +,-, and * are to be passed into other functions and found that these operators are defined by the following definition:
ghci> :t (*)
(*) :: (Num a) => a -> a -> a
However, when I run my code I get the following compilation error:
Illegal polymorphic or qualified type: Num a => a -> a -> a
Perhaps you intended to use RankNTypes or Rank2Types
In the type signature for ‘evalOp’:
evalOp :: EDict
-> ((Num a) => a -> a -> a) -> Expr -> Expr -> Maybe Double
I am not really sure why this is happening as I gave my function the proper parameters as defined by Haskell. Any help would be greatly appreciated as I am still very new to the language.
Right now, your Expr data type is constrained to Double-valued expressions, so there is no need to deal with polymorphism.
evalOp:: EDict -> (Double -> Double -> Double) -> Expr -> Expr -> Maybe Double
evalOp d op x y =
let r = eval d x
s = eval d y
in case (r, s) of
(Just m, Just n) -> Just (m `op` n)
_ -> Nothing
(+) :: Num a => a -> a -> a is a valid argument for evalOp, because its type can be "restricted" to Double -> Double -> Double.
> let f :: Double -> Double -> Double; f = (+)
> f 3 5
8.0
If your expression type were parameterized, then you would put a Num a constraint on your functions (not just on the arguments that involve a, because you want the same a throughout the function).
data Expr a
= Val a
| Add (Expr a) (Expr a)
| Mul (Expr a) (Expr a)
| Sub (Expr a) (Expr a)
| Dvd (Expr a) (Expr a)
| Var Id
| Def Id (Expr a) (Expr a)
deriving (Eq, Show)
type EDict a = Dict String a
evalOp:: Num a => EDict a -> (a -> a -> a) -> Expr a -> Expr a -> Maybe a
evalOp d op x y =
let r = eval d x
s = eval d y
in case (r, s) of
(Just m, Just n) -> Just (m `op` n)
_ -> Nothing
eval :: Num a => EDict a -> Expr a -> Maybe a
eval _ (Val x) = Just x
eval d (Var i) = find d i
eval d (Add x y) = evalOp d (+) x y
eval d (Mul x y) = evalOp d (*) x y
eval d (Sub x y) = evalOp d (-) x y
The error is telling you that you cannot nest a type qualifier inside one of the types in your function chain. Instead, put all of the qualifiers at the beginning of the type signature:
evalOp:: (Num a) => EDict -> (a -> a -> a) -> Expr -> Expr -> Maybe Double
See Haskell - Illegal Polymorphic type? for a more thorough discussion.
I have to understand the Deductive solver By Ted Yin from https://wiki.haskell.org/Nonogram
i don't know how
elim b w ps = filter (\p -> all (\x -> x `elem` p) b &&
all (\x -> x `notElem` p) w) ps
works. I only know that
all (\x -> x `notElem` [1]) [1,2,3,4]
gives False, and
all (\x -> x `elem` [1]) [1,1,1,1]
gives True.
but i don't know hot to run all elim function and how it works
First, help yourself to a little whitespace to aid understanding, and name your subexpressions:
elim b w ps = filter (\p -> all (\x -> x `elem` p) b &&
all (\x -> x `notElem` p) w
) ps
= filter foo ps
where
foo p = all (\x -> x `elem` p) b &&
all (\x -> x `notElem` p) w
= filter foo ps
where
foo p = all tst1 b && all tst2 w
where
tst1 = (\x -> x `elem` p)
tst2 = (\x -> x `notElem` p)
= filter foo ps
where
foo p = (&&) (all tst1 b) (all tst2 w)
where
tst1 x = elem x p
tst2 y = notElem y p
Now what does that do? Or better yet, what is it? Let's go by some types to build up our insight here:
filter :: (a -> Bool) -> [a] -> [a]
foo :: a -> Bool
ps :: [a]
filter foo ps :: [a]
p :: a
foo p :: Bool
(&&) :: Bool -> Bool -> Bool
all tst1 b :: Bool
all tst2 w :: Bool
---------------------------
all :: (t -> Bool) -> [t] -> Bool
tst1 :: t -> Bool
tst2 :: t -> Bool
b :: [t]
w :: [t]
---------------------------
......
---------------------------
elim b w ps :: [a]
elim :: [t] -> [t] -> [a] -> [a]
Complete the picture by working through the types of tst1 and tst2 to find out the relationship between the t and a types.
tst1 :: t -> Bool -- tst1 x = elem x p
tst2 :: t -> Bool -- tst2 y = notElem y p
x :: t
y :: t
elem :: Eq t => t -> [t] -> Bool
notElem :: Eq t => t -> [t] -> Bool
p :: [t] -- it was : a !
Thus a ~ [t] and [a] ~ [[t]] and finally,
elim b w ps :: [[t]]
elim :: Eq t => [t] -> [t] -> [[t]] -> [[t]]
So then filter foo leaves only those ps in ps for which foo p == True.
And that means all tst1 b == True and all tst2 w == True.
And that means, every x in b is an element of p, and every y in w is not an element in p. Or in other words only such ps in ps are left alone in the resulting list for which
foo p = (b \\ p) == [] && (p \\ w) == p
holds:
import Data.List (\\)
elim b w ps = [ p | p <- ps, (b \\ p) == [], (p \\ w) == p ]
I was having a look at some list operations and came across !!:
(!!) :: [a] -> Int -> a
xs !! n
| n < 0 = negIndex
| otherwise = foldr (\x r k -> case k of
0 -> x
_ -> r (k-1)) tooLarge xs n
The function (\x r k -> ...) has type a -> (Int -> a) -> Int -> a, but foldr takes a function that should only accept two arguments:
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr k z = go
where
go [] = z
go (y:ys) = y `k` go ys
Can someone explain to me why foldr accepts a function that takes 3 arguments with the following type a -> (Int -> a) -> Int -> a? Especially since the result should have the same type as the second argument?
-> is right-associative. So a -> b -> c is a -> (b -> c). Therefore, your type
a -> (Int -> a) -> Int -> a
is the same as
a -> (Int -> a) -> (Int -> a)
and we can see that it fits foldr's type quite well.
(more explanation for others ;)
(!!) :: [a] -> Int -> a
xs !! n
| n < 0 = negIndex
| otherwise = foldr (\x r k -> case k of
0 -> x
_ -> r (k-1)) tooLarge xs n
foldr :: (a -> b -> b) -> b -> [a] -> b
-- ^1 ^2
foldr commonly makes an accumulated(?) value. In this case, foldr makes an
accumulated function (b) of the type (Int -> a)! foldr ... tooLarge xs is evaluated to an
accumulated function, and this accumulated function (^2) takes an argument n. ^1 is a tooLarge function. Interestingly, the buildup of this
accumulated function depends on the value of a free variable n (i.e., k).
For example, ['a', 'b', 'c'] !! 2 is evaluated like below:
\x r k = \'a' r 2 -> r (2-1) (r is not known yet, and drives further evaluations.)
\x r k = \'b' r 1 -> r (1-1)
\x r k = \'c' r 0 -> 'c'
['a', 'b', 'c'] !! 3 goes like this:
\x r k = \'a' r 3 -> r (3-1)
\x r k = \'b' r 2 -> r (2-1)
\x r k = \'c' r 1 -> r (1-1) (r turns out to be tooLarge.) = tooLarge (1-1) (ERROR!)
You can check debug traces:
module Main where
import Debug.Trace
tooLarge _ = errorWithoutStackTrace "!!!: index too large"
negIndex = errorWithoutStackTrace "!!!: negative index"
(!!!) :: Show a => [a] -> Int -> a
xs !!! n
| n < 0 = negIndex
| otherwise = foldr (\x r k -> trace ("x: " ++ show x ++ ", k: " ++ show k) $
case k of
0 -> x
_ -> r (k-1)) tooLarge xs n
main = do
print $ ['a', 'b', 'c'] !!! 2
print $ ['a', 'b', 'c'] !!! 3
-- x: 'a', k: 2
-- x: 'b', k: 1
-- x: 'c', k: 0
-- 'c'
-- x: 'a', k: 3
-- x: 'b', k: 2
-- x: 'c', k: 1
-- sample: !!!: index too large
This (!!) implementation is a report version. The report version of the prelude is more efficient than a familiar naive recursive implementation,
due to optimizations of foldr.