在 oop 中,例如 java,只有当类型实际上是子类时,我们才能将超类向下转换为子类。
但是在 haskell 中,我们可以简单地将类型类“向下转换”为该类型类的任何实例。比如fromInteger
which 返回一个Num
. 从我的角度来看,它实际上是一个Int所以它不能被“向下转换”为Float但它可以。
Prelude System.Random> :t fromInteger a
fromInteger a :: Num a => a
Prelude System.Random> fromInteger 12 :: Int
12
Prelude System.Random> fromInteger 12 :: Float
12.0
再比如Random
改成 Int、Float 甚至 Bool
Prelude System.Random> let (a, g) = random (mkStdGen 12) :: (Int, StdGen)
Prelude System.Random> let (a, g) = random (mkStdGen 12) :: (Double, StdGen)
Prelude System.Random> let (a, g) = random (mkStdGen 12) :: (Bool, StdGen)
我们不知道 Random 实际上是什么,但我们可以将其“向下转换”为实例的类型,并且它始终 100% 有效。我不明白为什么它有效。