gpt4 book ai didi

scala - Haskell 诉 Scala 中的类型推断

转载 作者:行者123 更新时间:2023-12-04 22:11:25 24 4
gpt4 key购买 nike

鉴于以下代码:

Prelude> let f x = if (x) then 55 else "foo"

为什么编译器要寻找 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"

但是,在 Scala 中,它会找到 55"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

Haskell 和 Scala 的类型推断之间的主要区别是什么?

最佳答案

您可以在 Haskell 中为 Num [Char] 添加一个实例,如果这是您想要的:

{-# 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

这只是一种可能的实现。这将使您的示例编译:

> let f x = if x then 55 else "foo"
> f True
"55"
> f False
"foo"

Haskell 具有多态数字文字,因此 55 :: Num a => a ,并且由于 if 的两个分支必须返回相同的类型,因此您通过让 a ~ [Char] 分支返回 else 来强制 "foo" 。这会导致一些令人困惑的错误消息,但它可能是一个非常强大的功能。这意味着任何数字文字都可以作为您需要的类型,它与 OverloadedStrings 扩展背后的概念相同,允许您拥有多态字符串文字,而不是在需要 packText 的任何地方使用 ByteString

Scala 使用子类型化,并且所有值都有一个泛型类型。它允许您放宽函数的类型安全性,并从字面上返回 Any 事物。 Haskell 根本没有子类型,因此统一这些类型的唯一方法(类似于查找 LUB)是利用数字文字在 Num 约束下是多态的这一事实,因此为了编译 "foo" 必须实现 Num 。实际上,如果您启用 OverloadedStrings f 将编译得很好
f :: (Data.String.IsString a, Num a) => Bool -> a

默认情况下没有任何类型同时满足这两个约束,但 GHC 会很乐意接受它作为有效函数。

关于scala - Haskell 诉 Scala 中的类型推断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29950573/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com