为什么我不能在具有多态返回类型的函数中返回具体类型?

Har*_*air 1 polymorphism haskell typeclass

例如,为什么不能定义这样的函数 -

fun::a
fun = 1

-- OR

someInt::Int
someInt = 3

fun::Num a => a
fun = someInt
Run Code Online (Sandbox Code Playgroud)

看来这在 Java 中是可能的 -

class App {
    public static void main(String[] args) {
        System.out.println(new SomeClass().hello().sayHi());
    }
}

class SomeClass {
    Hi hello() {
        A a = new A();
        return a;
    }
}

interface Hi {
    String sayHi();
}

class A implements Hi {
    public String sayHi() {
        return "Hi from A";
    }
}

class B implements Hi {
    public String sayHi() {
        return "Hi from B";
    }
}
Run Code Online (Sandbox Code Playgroud)

但 Haskell 中的等价物不起作用 -

main = print $ sayHi hello

hello:: Hi a => a
hello = A

class Hi a where
  sayHi::a -> String
  
data A = A
data B = B

instance Hi A where
   sayHi _ = "Hi from A"
   
instance Hi B where
   sayHi _ = "Hi from B"
Run Code Online (Sandbox Code Playgroud)

我试图理解 Java 中的接口和 Haskell 中的类型类之间的根本区别?每种方法的局限性和优点是什么?

Wil*_*sem 5

具有以下功能:

hello :: Hi a => a
hello = A
Run Code Online (Sandbox Code Playgroud)

您向该函数的用户承诺,用户可以选择他们想要的任何函数 a,只要它是 的实例Hi a。所以这意味着用户可以使用:

hello :: A
hello :: B
Run Code Online (Sandbox Code Playgroud)

但这不是您的实现所显示的:它将始终返回一个A对象。从这个意义上说,面向对象编程(Java)和函数式编程(Haskell)中的类型约束在某种程度上彼此“相反”。在 Java 中,你承诺它将是子类,在 Haskell 中,你承诺它可以返回一个类型类的任何类型的Hi值。Hi

你的hello简单就是:

hello :: A
hello = A
Run Code Online (Sandbox Code Playgroud)

如果您随后hello在一个承诺它可以与任何项目一起使用的函数中使用Hi a => a,例如:

sayHi :: Hi a => a -> String
Run Code Online (Sandbox Code Playgroud)

它将因此a与统一A