Vaguely about Haskell's polymorphic types

I defined a function:

gen :: a -> b

So, just try a simple implementation:

gen 2 = "test"

But it gives an error:

gen.hs:51:9:
    Couldn't match expected type ‘b’ with actual type ‘[Char]’
      ‘b’ is a rigid type variable bound by
          the type signature for gen :: a -> b at gen.hs:50:8
    Relevant bindings include gen :: a -> b (bound at gen.hs:51:1)
    In the expression: "test"
    In an equation for ‘gen’: gen 2 = "test"
Failed, modules loaded: none.

So my function is wrong. Why is it anot typed as Int and bnot typed as String?

+4
source share
5 answers

This is a very common misunderstanding.

The key to understanding is that if you have a variable in your type signature, then the caller gets a decision about which type, not you!

, , " x", String; , . Int, Int. Bool, Bool.

, , String. , , . , .

, -, . () Java, , " Object", , . , , . Haskell , , .

: , , , a -> b, . . b . , , - , b, b , .

:

head :: [x] -> x

x ( " " ), x, ; , .

, gen :: a -> a . , , (.. id).

, , , Haskell.

+11

gen :: a -> b " a, b, foo a -> b", " a b, foo a -> b".

: - let x :: Int = gen "hello", , gen String -> Int , gen, , . a -> b, String -> Int, , . , ​​ a -> b, , , .

, . , - . , - . , ​​ Int. a -> b , .

+7

gen :: a -> b , a ( b, ).

, , gen 2 = "test" a String, , .

+2

. , , , , Java, Java.

Java :

  • :, , java.lang.Object
  • :, , List<T>.

Haskell (2). Haskell (1).

- ( , ++ ): , , , . , , List<T> , List<String>, List<List<String>> .., , , T .

, " ", , . , Java , "", :

List<String> myList = new ArrayList<String>();

, :

class MyFunction implements Function<Integer, String> {
    public String apply(Integer i) { ... }
}

- , , :

/**
 * Visitor-pattern style interface for a simple arithmetical language
 * abstract syntax tree.
 */
interface Expression {
    // The caller of `accept` implicitly chooses which type `R` is,
    // by supplying a `Visitor<R>` with `R` instantiated to something
    // of its choice.
    <R> accept(Expression.Visitor<R> visitor);

    static interface Visitor<R> {
        R constant(int i);
        R add(Expression a, Expression b);
        R multiply(Expression a, Expression b);
    }
}

Haskell . , gen :: a -> b, , a b, , gen. , " " , , gen, , a b; gen [()], a [()]. , , gen [()] , gen 2 = "test" , .

+1

Haskell , :

{-# LANGUAGE ScopedTypeVariables #-}

gen :: forall a b . a -> b
gen x = ????

"forall" - , & Lambda;. , gen - : , a, , b a, x. , . :

fst :: (a,b) -> a
fst (x1,x2) = x1

fst :: forall (a::*) (b::*) . (a,b) -> a
fst = /\ (a::*) -> /\ (b::*) -> \ (x::(a,b)) ->
   case x of
      (x1, x2) -> x1

* - ( ) . fst (3::Int, 'x'),

fst Int Char (3Int, 'x')

3Int Int 3. :

fst Int Char (3Int, 'x')
=
(/\ (a::*) -> /\ (b::*) -> \(x::(a,b)) -> case x of (x1,x2) -> x1) Int Char (3Int, 'x')
=
(/\ (b::*) -> \(x::(Int,b)) -> case x of (x1,x2) -> x1) Char (3Int, 'x')
=
(\(x::(Int,Char)) -> case x of (x1,x2) -> x1) (3Int, x)
=
case (3Int,x) of (x1,x2) -> x1
=
3Int

Regardless of the types I pass, as long as the value I pass in matches, the function fstwill be able to produce something of the required type. If you try to do this for a->b, you are stuck.

0
source

All Articles