
Hello Andrea, Saturday, August 26, 2006, 1:44:19 PM, you wrote:
perhaps this is silly, but it is not possible to declare function types?
could you please indicate me some documentation that explains this kind of stuff? So far I didn't find anything on that.
well, I've found something in the Report:
btw, i don't think that Report can be used to learn language, it's better to look into various tutorials or, even better, textbooks
6.1.6 Function Types Functions are an abstract type: no constructors directly create functional values. The following simple functions are found in the Prelude: id, const, (.), flip, ($), and until.
Now I'm trying to understand what "directly" stands for...
it's not something related to your question: Reports says here about functional values, not types :) i will try to make explanation you need. first, Haskell has a few primitive datatypes - Char, Int, Bool... second, it provides a way to construct new datatypes: data T = C1 Int Char | C2 Bool here, T is new type whose values can be constructed _only_ using C1 or C2 constructor. to be exact, we can construct value of type T, we can either apply C2 to value of another type, Bool, f.e. "C2 True", or by applying C1 to two values, Int and Char, f.e. C1 5 'a' 'newtype' declaration is equivalent to 'data', it just have some limitations 'type' _don't_ constructs any new type, it just adds type _synonym_ with sole purpose to simplify using of complex type constructions (it's just like 'typedef' in C if you know this language) for example, type String = [Char] allows us to use String in function signatures instead of [Char] Declarations of new types can have parameters: data T a b = C1 a b | C2 a Such declaration effectively declares a _family_ of different types what can be constructed by applying T2 type constructor to concrete types, f.e. "T2 Int String", "T2 Int Int" or even "T2 (T2 Int Int) String" In addition to predefined types (Int, Bool and so on) there are a number of predefined type constructors. Some of them are defined in Haskell itself: data Either a b = Left a | Right b data Maybe a = Just a | Nothing data [a] = a : [a] | [] Last definition is a bit artificial, but modulo specific syntax, list type constructor can be defined in Haskell proper: data List a = Cons a (List a) | Nil Function is among predefined type constructors, but it cannot be defined using Haskell itself: data (->) a b = .... But in all other aspects, '->' can be seen as ordinal type constructor which has two type parameters. This means that you don't need nor can't to define _new_ functional types using 'data' definition. But you can and should use type synonym declarations when you need to "specialize" (->) type constructor, i.e. give name to some concrete functional type, f.e. type HashFunction = (String->Int) This synonym can then be used in type specification like the right part in its definition, i.e. declarations createHash :: HashFunction -> IO Hash and createHash :: (String->Int) -> IO Hash are equivalent. So, technically speaking, you can't declare function types, there is only one predefined type constructor that can construct any function type you need. But from practical POV, you can define synonyms for any function type you've constructed using '->'. If you want, you can also declare parametric type synonyms: type HashFunction a = (a->Int) or something like type CPS a b = a -> Either a b It should be obvious that using parametric synonyms don't differ from using parameterless ones: createHash :: HashFunction Char -> IO (Hash Char) is translated into createHash :: (Char->Int) -> IO (Hash Char) Next point is that in Haskell functions are first-class values, i.e. you can hold them in data structures, pass as parameters to other functions and even return them as results. For example, the following function accepts function of type String->Int->Int and returns function of type (Int->Int): func :: (String->Int->Int) -> (Int->Int) func f = f "" The following data type includes function as one of its fields: data T = C (String->Int->Int) Int As i already said, newtype is just limited form of 'data' declaration, one which should use exactly one constructor with exactly one field, for example: newtype I = I Int Such restrictions guarantee that new type defined may use the same representation as its only field, and in fact newtype language construct guarantees it. But it is only internal representation, from the programmer's POV newtype is don't differs from 'data' Of course, newtype can also be used to define type whose only field contains some function: newtype F = F (String->Int) Again, in this case language guarantees that internal F representation will be the same as for plain (Int->String) function and therefore the same as for type synonym: type S = String->Int But from programmer POV, the difference still holds: while S denotes function of given type and can be used interchangeably with full notion of this function type, F is just the type which internally contains such function. Values of type F can be constructed, as for any other data type, only using F data constructor applied to function of corresponding type, f.e. "F length". So, "F length" has type F while 'length' itself may have type "String->Int" whose synonym is S hope that it helps :) -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com