## Specifying a function type signature in a where clause

reference to generic type requires arguments in

swift function type

method signature java

swift pass type as parameter

generic parameter is not used in function signature

swift generic return type

swift pass generic type as parameter

The following function implements the good old *filter* function from lists
by using the recursion-schemes library.

import Data.Functor.Foldable catafilter :: (a -> Bool) -> [a] -> [a] catafilter p = cata alg where -- alg :: ListF a [a] -> [a] alg Nil = [] alg (Cons x xs) = if (p x) then x : xs else xs

It compiles and a short test like `catafilter odd [1,2,3,4]`

is successful.
However, if I uncomment the type signature for `alg`

I get the following error:

src/cata.hs:8:30: error: • Couldn't match expected type ‘a’ with actual type ‘a1’ ‘a1’ is a rigid type variable bound by the type signature for: alg :: forall a1. ListF a1 [a1] -> [a1] at src/cata.hs:6:5-29 ‘a’ is a rigid type variable bound by the type signature for: catafilter :: forall a. (a -> Bool) -> [a] -> [a] at src/cata.hs:3:1-39 • In the first argument of ‘p’, namely ‘x’ In the expression: (p x) In the expression: if (p x) then x : xs else xs • Relevant bindings include xs :: [a1] (bound at src/cata.hs:8:18) x :: a1 (bound at src/cata.hs:8:16) alg :: ListF a1 [a1] -> [a1] (bound at src/cata.hs:7:5) p :: a -> Bool (bound at src/cata.hs:4:12) catafilter :: (a -> Bool) -> [a] -> [a] (bound at src/cata.hs:4:1) | 8 | alg (Cons x xs) = if (p x) then x : xs else xs | ^

The answer to the SO question type-signature-in-a-where-clause
suggests to use the *ScopedTypeVariables* extension.
The comment in the last answer to why-is-it-so-uncommon-to-use-type-signatures-in-where-clauses
suggests to use a *forall* quantification.

So I added:

{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE RankNTypes #-}

at the top of my module and tried different type signatures for *alg* like:
`alg :: forall a. ListF a [a] -> [a]`

or
`alg :: forall b. ListF b [b] -> [b]`

or adding a *forall* to the *catalist* type signature. Nothing compiled!

Question: Why I'm not able to specify a type signature for *alg*?

**Generic Parameters and Arguments,** A generic parameter clause specifies the type parameters of a generic type or rest of the type, function, or initializer declaration, including in the signature of The answer to the SO question type-signature-in-a-where-clause suggests to use the ScopedTypeVariables extension. The comment in the last answer to why-is-it-so-uncommon-to-use-type-signatures-in-where-clauses suggests to use a forall quantification.

This works

{-# Language ScopedTypeVariables #-} import Data.Functor.Foldable catafilter :: forall a. (a -> Bool) -> [a] -> [a] catafilter p = cata alg where alg :: ListF a [a] -> [a] alg Nil = [] alg (Cons x xs) = if (p x) then x : xs else xs

If you omit the `forall`

, these are completely different `a`

s (even though syntactically they are the same).

Because of implicit quantification, your uncommented version is taken to be

catafilter :: forall a. (a -> Bool) -> [a] -> [a] catafilter p = cata alg where alg :: forall a1. ListF a1 [a1] -> [a1] alg Nil = [] alg (Cons x xs) = if (p x) then x : xs else xs

This explains your error message:

Couldn't match expected type ‘a’ with actual type ‘a1’

The predicate (`p :: a -> Bool`

) expects an argument of type `a`

but it was given `x :: a1`

from `Cons x xs :: ListF a1 [a1]`

!

See if the explicitly quantified version makes sense given the bindings from the error message:

xs :: [a1] x :: a1 alg :: ListF a1 [a1] -> [a1] p :: a -> Bool catafilter :: (a -> Bool) -> [a] -> [a]

**where (generic type constraint),** The where clause in a generic definition specifies constraints on the types that are used as arguments for type parameters in a generic type, Specifying a function type signature in a where clause Hot Network Questions “Depend on abstractions, not on concretions” what is the exact meaning of this term

This works, and avoids all that counter-intuitive mucking around with `forall`

s

{-# LANGUAGE ScopedTypeVariables #-} import Data.Functor.Foldable catafilter :: (a -> Bool) -> [a] -> [a] catafilter p = cata alg where -- alg :: ListF a [a] -> [a] alg (Nil :: ListF aa [aa]) = [] :: [aa] alg (Cons x xs) = if (p x) then x : xs else xs

On the `alg Nil`

equation I could actually use tyvar `a`

: I used `aa`

merely to show they're distinct bindings. Because `aa`

appears on a pattern, the compiler unifies it with `a`

from the signature for `catafilter`

.

You could also/instead put the type annotations on the `alg Cons`

equation.

I understand @Jogger's confusion as to why ghc is so fussy about the position of the `forall`

; and the nervousness that a `forall`

perhaps indicates `RankNTypes`

.

**Type signature,** In computer science, a type signature or type annotation defines the inputs and outputs for a function, It specifies the general information about a function like the name, scope and parameters. Privacy policy · About Wikipedia · Disclaimers · Contact Wikipedia · Developers · Statistics · Cookie statement · Mobile view. As you know, F# uses type inference to deduce types, so you don’t often need to explicitly specify types in your code, especially for functions. But in order to work effectively in F#, you do need to understand the type syntax, so that you can build your own types, debug type errors, and understand function signatures.

The problem is that `alg`

depends on an external `p`

, so `alg`

's type can't be simply polymorphic.

One simple way around it is to make it independent of any external entities by passing them in as the function arguments, so that the function can have its simply polymorphic type as expected:

catafilter :: (a -> Bool) -> [a] -> [a] catafilter = cata . alg where alg :: (b -> Bool) -> ListF b [b] -> [b] alg p Nil = [] alg p (Cons x xs) = if (p x) then x : xs else xs

This doesn't need any language extensions.

**[Haskell-beginners] type signature error in a where clause,** November 2012, 22:04:15, Mark Wallace wrote: >> >>> I'm writing a merge sort function, but I get type error under such >>> implementation: The where clause can specify that the type is a class or a struct. The struct constraint removes the need to specify a base class constraint of System.ValueType. The System.ValueType type may not be used as a base class constraint.

**[PDF] Haskell Cheat Sheet,** a syntax error to give a variable or a function one of these names. The if statement has this “signature”: used here to specify which functions, types, con-. Program execution continues with the statement following the statement that called the Function procedure. Any number of Exit Function statements can appear anywhere in a Function procedure. Like a Sub procedure, a Function procedure is a separate procedure that can take arguments, perform a series of statements,

**Beginning Rust: From Novice to Professional,** The first statement is a declaration of a “trait” named "HasSquareRoot", A Rust trait is a container of function signatures; in this case it contains just one signature. or API, is implemented here for the specified types by the specified code. The requirements in a generic where clause specify that a type parameter inherits from a class or conforms to a protocol or protocol composition. Although the generic where clause provides syntactic sugar for expressing simple constraints on type parameters (for example, <T: Comparable> is equivalent to <T>

**Mastering Rust: Learn about memory safety, type system, ,** This is the most common syntax to specify trait bounds on generic items. We read the preceding function as follows show_me is a method that takes any type Using where clauses: This syntax is used when the type signature of any generic A function invocation (or call) is an expression, whose data type is that of the function. Before invoking a function, you must declare and define it. You can either declare it first (with function_declaration ) and then define it later in the same block, subprogram, or package (with function_definition ) or declare and define it at the same

##### Comments

- Try replacing
`p x`

with`undefined`

. Does the error go away? Why/why not? — Pass the predicate explicitly to`alg :: forall a1. (a1 -> Bool) -> ListF a1 [a1] -> [a1]`

with`catafilter = cata . alg`

. Which`forall`

s can you remove? Can you freely rename your type variables or not? - Thanks for your additional answer! For me it was important to have a normal type signature of the function
`alg`

as a compiler checkable signature and not only as a comment. A comment may be wrong. And thanks to the answers of chi and Icland_jack I now understand*forall* - I left the comment in from your O.P. It is the two type annotations that are doing the work, and they
*are*checked by the compiler.