Kev*_*ith 4 haskell scala type-inference
给出以下代码:
Prelude> let f x = if (x) then 55 else "foo"
Run Code Online (Sandbox Code Playgroud)
为什么编译器会寻找Num [Char]?
<interactive>:2:23:
No instance for (Num [Char]) arising from the literal `55'
In the expression: 55
In the expression: if (x) then 55 else "foo"
In an equation for `f': f x = if (x) then 55 else "foo"
Run Code Online (Sandbox Code Playgroud)
但是,在Scala中,它将找到55and 的最小上限"foo",即Any:
scala> def f(x: Boolean) = if (x) 55 else "foo"
f: (x: Boolean)Any
import scala.reflect.runtime.universe._
scala> lub( List[Type]( typeOf[Int], typeOf[String] ) )
res4: reflect.runtime.universe.Type = Any
Run Code Online (Sandbox Code Playgroud)
Haskell和Scala的类型推断之间的关键区别是什么?
您可以Num [Char]在Haskell中添加实例,如果这是您想要的:
{-# LANGUAGE FlexibleInstances #-}
import Data.Function (on)
import Data.Composition ((.:)) -- cabal install composition
helper :: (Integer -> Integer -> Integer) -> (String -> String -> String)
helper op = show .: on op read
cast :: (Integer -> Integer) -> (String -> String)
cast f = show . f . read
instance Num [Char] where
fromInteger = show
(+) = helper (+)
(-) = helper (-)
(*) = helper (*)
abs = cast abs
signum = cast signum
negate = cast negate
Run Code Online (Sandbox Code Playgroud)
这只是一种可能的实现方式.这将使您的示例编译:
> let f x = if x then 55 else "foo"
> f True
"55"
> f False
"foo"
Run Code Online (Sandbox Code Playgroud)
Haskell具有多态数字文字,因此55 :: Num a => a,并且由于两个分支if必须返回相同的类型,因此强制a ~ [Char]使else分支返回"foo".这会导致一些有些混乱的错误消息,但它可能是一个非常强大的功能.这意味着,任何数字文本可以根据你的需要的类型为行动,它的背后同样的概念OverloadedStrings扩展,让你有多态性字符串文本而不是使用pack无处不在,你需要一个Text或ByteString.
Scala使用子类型,并且所有值都具有泛型类型.它允许您放松功能上的类型安全性并返回字面上的Any东西.Haskell根本没有子类型,因此统一这些类型(类似于查找LUB)的唯一方法是使用数值文字在Num约束下是多态的这一事实,因此为了编译"foo"必须实现Num.实际上,如果你启用了OverloadedStrings f将与该类型编译得很好
f :: (Data.String.IsString a, Num a) => Bool -> a
Run Code Online (Sandbox Code Playgroud)
默认情况下,没有任何类型满足这两个约束,但GHC很乐意接受它作为有效函数.
| 归档时间: |
|
| 查看次数: |
219 次 |
| 最近记录: |