haskell for grownups - harrisonwl.github.io · haskell for grownups bill harrison february 8, 2019....

50
Haskell for Grownups Bill Harrison February 8, 2019

Upload: others

Post on 20-May-2020

34 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Haskell for Grownups

Bill Harrison

February 8, 2019

Page 2: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Table of Contents

IntroductionResources for HaskellHaskell vs. CTypes + Functions = Programs

PragmaticsModules are the basic unit of a Haskell programUsing GHCi

How to Write a Haskell Program

Page 3: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Haskell Basics

I Modern (pure) lazy functional language

I Statically typed, supports type inferenceI Compilers and interpreters:

I http://www.haskell.org/implementations.htmlI GHC CompilerI GHCi interpreter

I A peculiar language feature: indentation matters

I Also: capitalization matters

Page 4: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Some Reference Texts

I Programming in Haskell by Graham Hutton.This is an excellent, step-by-step introduction to Haskell.Graham also has a lot of online resources (slides, videos, etc.)to go along with the book.

I A Gentle Introduction to Haskell by Hudak, Peterson, andFasal.Available at http://www.haskell.org/tutorial/.

I Learn You a Haskell for Good by Miran Lipovaca.Highly amusing and informative; available online.

I Real World Haskell by Bryan O’Sullivan.Also available online (I believe). “Haskell for WorkingProgrammers”.

I Course notes and Slides by me.

I Google.

Page 5: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Question: What does this program do?

n = i;a = 1;while (n > 0) {

a = a * n;n = n - 1;

}

Page 6: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Functions in Mathematics

n! =

{1 if n = 0n ∗ (n − 1)! if n > 0

What does this have to do with that?

n = i;a = 1;while (n > 0) {

a = a * n;n = n - 1;

}

Page 7: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Functions in Mathematics

n! =

{1 if n = 0n ∗ (n − 1)! if n > 0

What does this have to do with that?

n = i;a = 1;while (n > 0) {

a = a * n;n = n - 1;

}

Page 8: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

First Haskell Function

n! =

{1 if n = 0n ∗ (n − 1)! if n > 0

It’s relationship to this Haskell function is apparent:

fac :: Int -> Intfac 0 = 1fac n = n * fac (n-1)

Page 9: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

First Haskell Function

n! =

{1 if n = 0n ∗ (n − 1)! if n > 0

It’s relationship to this Haskell function is apparent:

fac :: Int -> Intfac 0 = 1fac n = n * fac (n-1)

Page 10: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Hello World in C

#include <stdio.h>int main() {printf("hello world\n");

}

Page 11: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Hello World in Haskell

module HelloWorld wherehelloworld :: IO ()helloworld = print "Hello World"

Page 12: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Factorial Revisited

#include <stdio.h>int fac(int n) {if (n==0){ return 1; }

else{ return (n * fac (n-1)); }

}

int main() {printf("Factorial 5 = %d\n",fac(5));return 0;

}

Page 13: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Hello Factorial

#include <stdio.h>int fac(int n) {printf("hello world"); // newif (n==0){ return 1; }

else{ return (n * fac (n-1)); }

}...

(N.b., the type is the same)

int fac(int n) {...}

Page 14: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Hello Factorial

#include <stdio.h>int fac(int n) {printf("hello world"); // newif (n==0){ return 1; }

else{ return (n * fac (n-1)); }

}...

(N.b., the type is the same)

int fac(int n) {...}

Page 15: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Hello Factorial in Haskell

fac :: Int -> IO Int -- the type changedfac 0 = do print "hello world"

return 1fac n = do print "hello world"

i <- fac (n-1)return (n * i)

Page 16: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Data Types + Functions = Haskell ProgramsHaskell programming is both data type and functional programming!

I Arithmetic interpreterI data type:

data Exp = Const Int | Neg Exp | Add Exp Exp

I function:

interp :: Exp -> Intinterp (Const i) = iinterp (Neg e) = - (interp e)interp (Add e1 e2) = interp e1 + interp e2

I How do Haskell programs use data?I Patterns break data apart to access:

“interp (Neg e) =. . .”I Functions recombine into new data:

“interp e1 + interp e2”

Page 17: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Data Types + Functions = Haskell ProgramsHaskell programming is both data type and functional programming!

I Arithmetic interpreterI data type:

data Exp = Const Int | Neg Exp | Add Exp Exp

I function:

interp :: Exp -> Intinterp (Const i) = iinterp (Neg e) = - (interp e)interp (Add e1 e2) = interp e1 + interp e2

I How do Haskell programs use data?I Patterns break data apart to access:

“interp (Neg e) =. . .”I Functions recombine into new data:

“interp e1 + interp e2”

Page 18: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Type Synonym

Type synonym: new name for an existing type; e.g.,

type String = [Char]

String is a synonym for the type [Char].

Page 19: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Type synonyms can be used to make other types easier to read;e.g., given:

type Pos = (Int,Int)

origin :: Posorigin = (0,0)left :: Pos -> Posleft (x,y) = (x-1,y)

Page 20: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Parametric PolymorphismType synonyms can also have parameters

type Pair a = (a,a)

mult :: Pair Int -> Intmult (m,n) = m*n

copy :: a -> Pair acopy x = (x,x)

Page 21: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Nesting Type SynonymsType declarations can be nested

type Pos = (Int,Int) -- GOOD

type Trans = Pos -> Pos -- GOOD

However, they cannot be recursive:

type Tree = (Int,[Tree]) -- BAD

Page 22: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Data Declarations

A completely new type can be defined by specifying its valuesusing a data declaration.

data Bool = False | True

I Bool is a new type.

I False and True are called constructors for Bool.

I Type and constructor names begin with upper-case letters.

I Data declarations are similar to context free grammars.

Page 23: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Data Declarations

A completely new type can be defined by specifying its valuesusing a data declaration.

data Bool = False | True

I Bool is a new type.

I False and True are called constructors for Bool.

I Type and constructor names begin with upper-case letters.

I Data declarations are similar to context free grammars.

Page 24: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

New types can be used in the same way as built-in types

For example, given

data Answer = Yes | No | Unknown

We can define:

answers :: [Answer]answers = [Yes,No,Unknown]

flip :: Answer -> Answerflip Yes = Noflip No = Yesflip Unknown = Unknown

Page 25: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

New types can be used in the same way as built-in types

For example, given

data Answer = Yes | No | Unknown

We can define:

answers :: [Answer]answers = [Yes,No,Unknown]

flip :: Answer -> Answerflip Yes = Noflip No = Yesflip Unknown = Unknown

Page 26: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Constructors with ParametersThe constructors in a data declaration can also have parameters.For example, given

data Shape = Circle Float| Rect Float Float

we can define:

square :: Float -> Shapesquare n = Rect n narea :: Shape -> Floatarea (Circle r) = pi * rˆ2area (Rect x y) = x * y

Page 27: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Note:

I Shape has values of the form Circle r where r is a float, andRect x y where x and y are floats.

I Circle and Rect can be viewed as functions that constructvalues of type Shape:

-- Not a definitionCircle :: Float -> ShapeRect :: Float -> Float -> Shape

Page 28: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Not surprisingly, data declarations themselves can also haveparameters. For example, given

data Maybe a = Nothing | Just a

we can define:

safediv :: Int -> Int -> Maybe Intsafediv _ 0 = Nothingsafediv m n = Just (m ‘div‘ n)

safehead :: [a] -> Maybe asafehead [] = Nothingsafehead xs = Just (head xs)

Page 29: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Table of Contents

IntroductionResources for HaskellHaskell vs. CTypes + Functions = Programs

PragmaticsModules are the basic unit of a Haskell programUsing GHCi

How to Write a Haskell Program

Page 30: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

General form of a Haskell module

module ModuleName whereimport L1 -- imports

...import Lk

data D1 = · · · -- type decls

...data Dn = · · ·

f1 = · · · -- fun decls

...fm = · · ·

I Order does not matter

I Modules, Types &constructors are alwayscapitalized

I Module ModuleName storedin file, ModuleName.hs

Page 31: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Starting GHCi

bash-3.2> ghciGHCi, version 7.6.3: http://www.haskell.org/ghc/ :? for helpLoading package ghc-prim ... linking ... done.Loading package integer-gmp ... linking ... done.Loading package base ... linking ... done.

*Prelude>

Page 32: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Loading a File into GHCi

*Prelude> :l ExtractList[1 of 1] Compiling ExtractList (ExtractList.hs, interpreted)Ok, modules loaded: ExtractList.

*ExtractList>

I :l is short for :load.

I Could type ghci ExtractList to load it at start up.

Page 33: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Checking Types in GHCi

*ExtractList> :t headhead :: [a] -> a

*ExtractList> :t tailtail :: [a] -> [a]

*ExtractList> :t (:)(:) :: a -> [a] -> [a]

I :t is short for :type.I Can check the type of any function definition

I The above are list functions defined in Prelude

Page 34: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Reloading and Quitting GHCi

*ExtractList> :rOk, modules loaded: ExtractList.

*ExtractList> :qLeaving GHCi.bash-3.2>

I :r is short for :reload.

I :q is short for :quit.

I Reload only recompiles the current module. Use it when youhave only made changes to the current module—it’s faster.

I Emacs Users: can use C-p, C-n, C-e, C-a, C-f at the GHCiprompt to cycle through and edit previous commands.

Page 35: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Table of Contents

IntroductionResources for HaskellHaskell vs. CTypes + Functions = Programs

PragmaticsModules are the basic unit of a Haskell programUsing GHCi

How to Write a Haskell Program

Page 36: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Type-Driven Programming in HaskellTypes first, then programs

I Writing a function with type A→ B, then you have a lot ofinformation to use for fleshing out the function.

I Why? Because the input type A — whatever it happens to be— has a particular form that determines a large part of thefunction itself.

I This is, in fact, the way that you should develop Haskellprograms.

Page 37: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Recursive Types

In Haskell, new types can be declared in terms of themselves. Thatis, types can be recursive.

data Nat = Zero | Succ Nat

Nat is a new type, with constructors

Zero :: NatSucc :: Nat -> Nat

Page 38: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Note:

I A value of type Nat is either Zero, or of the form Succ nwhere n :: Nat. That is, Nat contains the following infinitesequence of values:

ZeroSucc ZeroSucc (Succ Zero)

...

Page 39: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Note:

I We can think of values of type Nat as natural numbers, whereZero represents 0, and Succ represents the successorfunction 1+.

I For example, the value

Succ (Succ (Succ Zero))

represents the natural number

1 + (1 + (1 + 0))

Page 40: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Using recursion, it is easy to define functions that convert betweenvalues of type Nat and Int:

nat2int :: Nat -> Intnat2int Zero = 0nat2int (Succ n) = 1 + nat2int n

int2nat :: Int -> Natint2nat 0 = Zeroint2nat n = Succ (int2nat (n - 1))

Page 41: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Two naturals can be added by converting them to integers,adding, and then converting back:

add :: Nat -> Nat -> Natadd m n = int2nat (nat2int m + nat2int n)

However, using recursion the function add can be definedwithout the need for conversions:

add Zero n = nadd (Succ m) n = Succ (add m n)

The recursive definition for add corresponds to the laws

0 + n = n

and(1 + m) + n = 1 + (m + n)

Page 42: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

The edit-compile-test-until-done paradigmI’m guessing that this is familar to you

When I was a student—the process of writing a C program tendedto follow these steps:

1. Create/edit a version of the whole program using a text editor.

2. Compile. If there were compilation errors, develop ahypothesis about what the causes were and start again at 1.

3. Run the program on some tests. Do I get what I expect? Ifso, then declare victory and stop; otherwise, develop ahypothesis about what the causes were and start again at 1.

Page 43: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

An Exercise

I Write a function that

1. takes a list of items,2. takes a function that returns either True or False on those

items,3. and returns a list of all the items on which the function is true.

I This is called filter , and it’s a built-in function in Haskell, butlet me show you how I’d write it from scratch.

I I call the function I’m writing “myfilter” to avoid the nameclash with the built-in version.

Page 44: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Step 1. Figure out the type of the thing you’re writing

I Think about the type of filter and write it down as a typespecification in a Haskell module (called Sandboxthroughout).

I With what I’ve said about filter, it takes a list ofitems—i.e., something of type [a].

I It also takes a function that takes an item—an a thing—andreturns true or false—i.e., it returns a Bool. So, this functionwill have type a → Bool.

I ∴ the type should be:

myfilter :: [a] -> (a -> Bool) -> [a]

Page 45: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Step 2: Fill in the type template & Load the module.

I In this case, we have a function with two arguments. Thesecond argument of type a->Bool does not have amatchable form like the first argument.

I This leaves us with:myfilter :: [a] -> (a -> Bool) -> [a]myfilter [] f = undefinedmyfilter (x:xs) = undefined

I Reloading module reveals an error in the template as typed:> ghci Sandbox.hs[1 of 1] Compiling Sandbox ( Sandbox.hs, interpreted )Sandbox.hs:6:1:

Equations for ‘myfilter’ have different numbers of argumentsSandbox.hs:6:1-27Sandbox.hs:7:1-27

Page 46: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Step 2: Fill in the type template & Load the module.

I In this case, we have a function with two arguments. Thesecond argument of type a->Bool does not have amatchable form like the first argument.

I This leaves us with:myfilter :: [a] -> (a -> Bool) -> [a]myfilter [] f = undefinedmyfilter (x:xs) = undefined

I Reloading module reveals an error in the template as typed:> ghci Sandbox.hs[1 of 1] Compiling Sandbox ( Sandbox.hs, interpreted )Sandbox.hs:6:1:

Equations for ‘myfilter’ have different numbers of argumentsSandbox.hs:6:1-27Sandbox.hs:7:1-27

Page 47: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Step 2 (continued)Debugging via Type-checking!

I Fix the error NOW! Forgot 2nd f param. in 2nd clause.I Type error just committed can be fixed now.I Alternative: wait until I have “first draft” of the whole

program and check it.I Incremental approach: can check each new part of the

program as I create it so that I’m not surprised by errors.I Identifying the source of error easier—i.e., it is the line you

just typed.

I Fixing the error yields:

myfilter :: [a] -> (a -> Bool) -> [a]myfilter [] f = undefinedmyfilter (x:xs) f = undefined

Page 48: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Step 3: Fill in the clauses one-by-one reloading as you go.

The [] case is obvious because there is nothing to filter out:

myfilter :: [a] -> (a -> Bool) -> [a]myfilter [] f = []myfilter (x:xs) f = undefined

No problems with this last bit:

> ghci Sandbox.hs[1 of 1] Compiling SandboxOk, modules loaded: Sandbox.

*Sandbox>

Page 49: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Step 3 (continued).

I The second clause should only include x if f x is True; oneway to write that is with an if−then−else:

myfilter :: [a] -> (a -> Bool) -> [a]myfilter [] f = []myfilter (x:xs) f = if f x

then x : myfilter f xselse myfilter f xs

I Loading this into GHC reveals a problem:> ghci Sandbox.hs[1 of 1] Compiling Sandbox ( Sandbox.hs, interpreted )Sandbox.hs:8:46:

Couldn’t match expected type ‘[a]’ with actual type ‘a -> Bool’In the first argument of ‘myfilter’, namely ‘f’In the second argument of ‘(:)’, namely ‘myfilter f xs’In the expression: x : myfilter f xs

Failed, modules loaded: none.Prelude>

Page 50: Haskell for Grownups - harrisonwl.github.io · Haskell for Grownups Bill Harrison February 8, 2019. Table of Contents Introduction Resources for Haskell Haskell vs. C Types + Functions

Step 3 (continued).

I This error occurs on line 8 of the module, which is the line“then x : myfilter f xs”. GHCi is telling us that itexpects that f would have type [a] but that it can see that fhas type a → Bool. After a moment’s pause, we can seethat the order of the arguments is incorrect in both recursivecalls. The corrected version works:

myfilter :: [a] -> (a -> Bool) -> [a]myfilter [] f = []myfilter (x:xs) f = if f x

then x : myfilter xs felse myfilter xs f