1/39
Looks like no tags are added yet.
Name | Mastery | Learn | Test | Matching | Spaced | Call with Kai |
|---|
No analytics yet
Send a link to your students to track their progress
How can recursion cause peformance issues?
Can cause stack overflow for large inputs, where each recursive call waits for the result of the next call, which leads to deep stack usage
Why is recursion useful?
Some functions, such as factorial, are simpler to define
What is tail recursion?
When the recursive call is the last operation in the function, which allows Haskell to reuse the same stack frame instead of creating new ones
Why is tail recursion better than normal recursion?
It optimises memory usage by avoiding deep call stacks
What is a higher-order function?
If it takes a function as an argument or returns a function as a result
Why are higher-order functions useful? (3 reasons)
Common programming patterns can be encoded as functions within the language itself, where many repetitive programming patterns can be expressed as reusable higher-order functions
Allows for flexible and reusable functions, where returning functions as value enables partial application in currying, making it easy to write specialised functions
Enable function composition, where we can combine functions to create more complex behaviours
What are local bindings?
Variables or functions that are defined within a certain scope, usually inside a function
Why are local bindings useful?
They help keep code organised, readable, and avoid unnecessary repetition by restricting certain definitions to where they are needed
What are list or set comprehensions?
Can be used to construct new sets from old sets, or new lists from old lists
What are the use of guards in generators?
List comprehensions can use guards to restrict values produced by earlier generators
How do string comprehensions work like list comprehensions?
Strings in Haskell are just a list of characters, so any polymorphic function that operates on lists can also be applied to strings
What is the difference between a strongly and statically typed language?
A strongly typed language is once a type is assigned to a value, that type cannot change which ensures operations on data are performed correctly, and prevents a wide class of errors.
A statically typed language is when types are determined at compile time, where many errors related to types are caught early before execution.
What is a polymorphic function?
A function whose type signature contains one or more type variables, for example: a length of a list function would have a list of type, a, an ambiguous type since you are basically saying you are allowing any type to be in the list (Int, Bool, String, etc.).
What are type classes?
Essentially a collection of types that all support a specific set of operations, which are called methods. You can think of them as interfaces that define certain behaviours.
What does the Numeric (Num) type contain and do?
Contains numeric types (like Int, Integer, Float) and provides methods for (+), (-), (*), negate, abs, and signum.
It does NOT provide a method for division.
What does the Integral and Fractional types contain and do?
Contains specific numeric classes, where Integral is for whole numbers like Int and provides integer division (div) and modulus (mod), whereas Fractional is for non-integers like Float and provides standard fractional division (/) and reciprocation (recip).
Describe the difference between Int and Integer.
Int has a limit (depending on computer architecture, 32 and 64-bit) whereas Integer can hold much more than that.
What does the Equality (Eq) type contain and do?
Contains types whose values can be checked for equality (==) and inequality (/=)
What does the Ordered (Ord) type contain and do?
Contains types that are linearly ordered, so you can compare them using <, >, <=, and >=, as well as min and max.
To be an instance of Ord, you MUST be an instance of Eq.
What does the Show and Read class contain and do?
Types in the Show class can be converted into strings (useful for printing to the terminal), while types in the Read class can be parsed from strings back into values.
What is an overloaded function?
Specific type of polymorphic function whose type signature contains one or more class constraints.
e.g. (+), which has the type signature Num a => a -> a -> a. The Num a => portion is the class constraint. This tells the compiler that the function works for any type a, but only if a is a numeric type.
Why can’t something like Int be a class constraint?
A class constraint cannot be a concrete data type like Int, but a type class like Num or Ord or Eq, etc.
What are curried functions?
A function that processes its arguments one at a time, rather than taking them all together at once in a structure like a tuple. It achieves this by taking the first argument and returning a nested function, which then takes the next argument, and so on until all arguments are evaluated.
Why is currying useful?
It enables partial application (supply a function with fewer arguments than it ultimately requires), making functions highly flexible and reusable.
Why are lambda’s useful?
Can be used to give a formal meaning to functions defined using currying, and can be used to avoid naming functions that are only referenced once.
What is a total function?
A function that is defined for all possible inputs of its type, and always terminates.
What is a partial function?
A function that is not defined for some inputs or can result in runtime errors or non-termination.
Why are total functions good?
They ensure absence of runtime errors due to unhandled cases or invalid inputs, and they behave predictably.
Are lists homogenious or heterogenious, and what does it mean?
Lists are homogenious, which means every element inside a list must be the exact same data type.
Are tuples homogenious or heterogenious, and what does it mean?
Tuples are heterogenious, which means it can contains values with different data types.
Why are tuples useful?
Provides a way to return multiple values from a function.
What is the “type” keyword and what is its uses?
It is used to create transparent aliases for existing data types, similarly to typedef in C. Its main purpose is to make complex or long type signatures easier to read and understand throughout your program.
This means “type Age = Int” is still treated as an Int even though we called it “Age”, the compiler treats it the same.
What is the “newtype” keyword and what is its uses?
It is used to wrap an existing type to define a brand new type, it must be defined with exactly 1 data constructor which usually shares the same name as the new type you are defining. (e.g. newtype Age = Age Int).
Since we are creating a new data type, the compiler will see it as such and will not allow us to pass through an Int into Age, but only Age.
What is the “deriving” keyword and what is its uses?
Allows you to add standard behaviours for your custom “newtype”, such as Show, Eq, or Ord.
What is the “data” keyword and what is its uses?
The primary way to define brand new data types from scratch, and works similar to enums in languages such as Java. It can also be used to hold additional values, create generics (like in Java) and recursive data types.
Give advantages of using local bindings.
They help keep code organised, readable and avoid repetition by restricting definitions to where they are needed.
What are pure functions?
A function whose return value is entirely determined by the arguments passed to it.
List some benefits of using pure functions.
Highly predictable since functional programming relies on pure functions and immutable data
Compiler optimisations since the compiler could cache the result for future use or call a function multiple times.
No side-effects to outside world, such as reading or writing to a file.
Give an example of a non-pure function.
IO Action.