Haskell fromIntegral或read是如何工作的
Haskell fromIntegral或read是如何工作的,haskell,polymorphism,Haskell,Polymorphism,fromIntegral返回一个Num数据类型。但似乎Num能够强制执行Double或Integer而没有问题。类似地,read函数能够返回符合其类型签名所需的任何内容。这是怎么回事?如果我真的需要做一个类似的函数,我该怎么做呢?类型检查器不仅可以推断函数参数的类型,还可以推断返回类型。事实上,那里没有特殊情况。如果在Integer中存储integral或read的结果,将调用此类型的版本。您可以用同样的方法创建自己的函数 例如: class Foo a where foo :: a in
fromIntegral
返回一个Num
数据类型。但似乎Num
能够强制执行Double
或Integer
而没有问题。类似地,read
函数能够返回符合其类型签名所需的任何内容。这是怎么回事?如果我真的需要做一个类似的函数,我该怎么做呢?类型检查器不仅可以推断函数参数的类型,还可以推断返回类型。事实上,那里没有特殊情况。如果在Integer
中存储integral或read
的结果,将调用此类型的版本。您可以用同样的方法创建自己的函数
例如:
class Foo a where
foo :: a
instance Foo Integer where
foo = 7
instance Foo String where
foo = "Hello"
x :: Integer
x = 3
main = do
putStrLn foo
print (foo + x)
twice :: a -> [a]
twice a = [a,a]
y :: [Integer]
y = twice foo
因为putStrLn
具有类型String->IO()
类型检查器发现putStrLn foo
中的foo
类型必须是String
,程序才能编译。foo
的类型是fooa=>a
。因此它推断出a==String
并搜索foostring
实例。这样的实例存在,它会导致在那里选择foo::foo String=>String
值
类似的推理发生在print(foo+x)
中x
已知为Integer
,并且由于(+)
的类型为Num a=>a->a->a
类型检查器推断加法运算符的左参数也必须是Integer
,因此它搜索Foo Integer
实例并替换Integer
变量
<> C++中没有函数指令到(可能)返回类型的方向。类型检查器甚至可以根据函数预期返回的内容推断函数参数。另一个例子:
class Foo a where
foo :: a
instance Foo Integer where
foo = 7
instance Foo String where
foo = "Hello"
x :: Integer
x = 3
main = do
putStrLn foo
print (foo + x)
twice :: a -> [a]
twice a = [a,a]
y :: [Integer]
y = twice foo
这里的函数参数的类型是fooa=>a
,它不足以决定使用哪个Foo
。但是,由于已知结果是[Integer]
,类型检查器发现它必须向提供两次Integer
类型的值,并且通过使用foo
的适当实例,类型检查器不仅能够推断函数参数的类型,而且能够推断返回类型。事实上,那里没有特殊情况。如果在Integer
中存储integral
或read
的结果,将调用此类型的版本。您可以用同样的方法创建自己的函数
例如:
class Foo a where
foo :: a
instance Foo Integer where
foo = 7
instance Foo String where
foo = "Hello"
x :: Integer
x = 3
main = do
putStrLn foo
print (foo + x)
twice :: a -> [a]
twice a = [a,a]
y :: [Integer]
y = twice foo
因为putStrLn
具有类型String->IO()
类型检查器发现putStrLn foo
中的foo
类型必须是String
,程序才能编译。foo
的类型是fooa=>a
。因此它推断出a==String
并搜索foostring
实例。这样的实例存在,它会导致在那里选择foo::foo String=>String
值
类似的推理发生在print(foo+x)
中x
已知为Integer
,并且由于(+)
的类型为Num a=>a->a->a
类型检查器推断加法运算符的左参数也必须是Integer
,因此它搜索Foo Integer
实例并替换Integer
变量
<> C++中没有函数指令到(可能)返回类型的方向。类型检查器甚至可以根据函数预期返回的内容推断函数参数。另一个例子:
class Foo a where
foo :: a
instance Foo Integer where
foo = 7
instance Foo String where
foo = "Hello"
x :: Integer
x = 3
main = do
putStrLn foo
print (foo + x)
twice :: a -> [a]
twice a = [a,a]
y :: [Integer]
y = twice foo
这里的函数参数的类型是fooa=>a
,它不足以决定使用哪个Foo
。但因为已知结果是[Integer]
类型检查器发现它必须向提供两次整型值,并通过使用foo
的适当实例来执行此操作。read
是的成员,这意味着它的实现可以依赖于类型参数
此外,像1
、42
等数字文字是函数调用fromInteger 1
、fromInteger 42
等的语法糖类,而fromInteger
本身是Num typeclass的成员
因此,文本42
(或from integer 42
)可以返回Int
或Double
或任何其他Num实例,具体取决于调用它的上下文。read
是的成员,这意味着它的实现可以依赖于类型参数
此外,像1
、42
等数字文字是函数调用fromInteger 1
、fromInteger 42
等的语法糖类,而fromInteger
本身是Num typeclass的成员
因此,文本42
(或from integer 42
)可以返回Int
或Double
或任何其他Num实例,具体取决于调用它的上下文。我对这里的术语有点挑剔,因为我觉得你说的这些话暴露了你对Haskell工作原理的误解
fromIntegral返回Num数据类型
更准确地说,fromIntegral
将具有类Integral
实例的任何类型作为输入,并可以返回属于类Num
实例的任何类型。前奏曲对它的定义如下:
fromIntegral :: (Integral a, Num b) => a -> b
fromIntegral = fromInteger . toInteger
带有Integral
实例的类型实现toInteger
函数,所有带有Num
实例的类型实现fromInteger
fromIntegral
使用与Integral a
实例关联的toInteger
将a
类型的值转换为整数。然后它使用<