Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I declare the type of a function defined within a let

I want to write something like:

f :: (a -> b) -> a -> c -> b
f g =
   let inner :: a -> c -> b
       inner x y = g x
   in inner

but this gives me an error.because it doesn't recognize that I'm trying to refer to the same "a" and "b" types as in the declaration as f

How can I explicitly give the proper type for inner?

like image 582
dspyz Avatar asked May 20 '14 01:05

dspyz


People also ask

How do you define type of function?

The types of functions are defined on the basis of the domain, range, and function expression. The expression used to write the function is the prime defining factor for a function. Along with expression, the relationship between the elements of the domain set and the range set also accounts for the type of function.

How do you define a function in #define?

A function can be defined as a relation between a set of inputs where each input has exactly one output.

How is a function declared and defined?

Definition. Function declaration is a prototype that specifies the function name, return types and parameters without the function body. Function Definition, on the other hand, refers to the actual function that specifies the function name, return types and parameters with the function body.

Can we declare a variable using let?

let allows you to declare variables that are limited to the scope of a block statement, or expression on which it is used, unlike the var keyword, which declares a variable globally, or locally to an entire function regardless of block scope.


2 Answers

You'll need the extension ScopedTypeVariables. You also need to add an explicit forall a b c . to your signature, which signals to bind the variables for the whole scope of the definition.

{-# LANGUAGE ScopedTypeVariables #-}

f :: forall a b c . (a -> b) -> a -> c -> b
f g =
   let inner :: a -> c -> b
       inner x y = g x
   in inner
like image 86
crockeea Avatar answered Oct 23 '22 01:10

crockeea


One way to do this would be to bind the outer and inner types by making g a parameter in inner, like this....

f g =
   let inner :: (a->b)->a -> c -> b
       inner g x y = g x
   in inner g

This does change your structure slightly though.... And possibly negates the reason to have an inner let in the first place, but in many cases (depending on the larger program) this might help.

like image 25
jamshidh Avatar answered Oct 23 '22 02:10

jamshidh