输入数字的签名加倍? [英] Type signature of num to double?

查看:123
本文介绍了输入数字的签名加倍?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚开始了解你对Haskell的好处,并且对类型类有点麻烦。我想创建一个可以使用任何数字类型的函数,并强制它成为一个double类型。



我的第一个想法是定义

  numToDouble :: Num  - > Double 

但我不认为这是因为 Num 不是类型,它是一个 typeclass (在我看来,它是一组类型)。所以看 read ,显示(Read a)=>字符串 - >一个。我正在阅读它,因为read需要一个字符串,并返回一个类型为 a 的用户指定的东西。所以我写了下面的内容:

  numToDouble ::(Num n)=> n  - > Double 
numToDouble i =((i):: Double)

取出类型为n的东西(必须在 Num typeclass中,并将其转换为Double。这似乎是合理的,因为我可以做 20: :Double



这会产生以下输出

 不能从上下文(Num n)
中推导出(n〜Double)
由numToDouble :: Num的类型签名绑定$ n $> n - > Double

我有我不知道我在读什么。基于我能找到的东西,似乎这与多态性有关?

编辑:



要清楚的是,我的问题是:为什么这不起作用?

解决方案

可以说20 :: Double是Haskell中的一个整数字面值类型为Num a => a,这意味着它可以是任何你喜欢的数字类型。



你是正确的,typeclass是一组类型。确切地说,它是在类型类的where子句中实现函数的一组类型。您的numToDouble类型签名正确地表达了您想要执行的操作。



您所知道的函数中的类型n的值是它实现了Num接口。这由+, - ,*,negate,abs,signum和fromInteger组成。最后一个是唯一一个可以进行类型转换的函数,但它并不适用于你想要的。

numToDouble应该怎么做?正确的事情并不明显,这是你遇到问题的原因之一。



然而,降低类型层次结构时,您需要Real类型类别,它具有所有您可能想要使用的更直接的数字类型,如浮点数,双精度和各种整数类型。这包括一个函数toRational,它可以将任何实际值转换为一个比率,从中可以使用fromRational将其转换为Double,这是Fractional类型类型的一个函数。

所以试试:

  toDouble ::(Real n)=> n  - > Double 
toDouble = fromRational。 toRational

但当然这实际上太具体了。 GHCI说:

  Prelude> :输入fromRational。从国民收入中扣除
。 toRational ::(分数c,实数a)=> a - > c

因此它将任何实际类型转换为任何分数类型(后者涵盖任何可以进行分割,包括那些不是Real实例的东西,比如Complex)当用数字类型搞乱时,我总是发现自己把它用作一种通用的数字强制。

编辑:正如leftaroundabout所说,

  realToFrac = fromRational。 toRational 


I'm just starting Learn You a Haskell for Great Good, and I'm having a bit of trouble with type classes. I would like to create a function that takes any number type and forces it to be a double.

My first thought was to define

numToDouble :: Num -> Double

But I don't think that worked because Num isn't a type, it's a typeclass (which seems to me to be a set of types). So looking at read, shows (Read a) => String -> a. I'm reading that as "read takes a string, and returns a thing of type a which is specified by the user". So I wrote the following

numToDouble :: (Num n) => n -> Double
numToDouble i = ((i) :: Double)

Which looks to me like "take thing of type n (must be in the Num typeclass, and convert it to a Double". This seems reasonable becuase I can do 20::Double

This produces the following output

Could not deduce (n ~ Double)                                                                                                                                                                                                                                              
from the context (Num n)                                                                                                                                                                                                                                                   
  bound by the type signature for numToDouble :: Num n => n -> Double

I have no idea what I'm reading. Based on what I can find, it seems like this has something to do with polymorphism?

Edit:

To be clear, my question is: Why isn't this working?

解决方案

The reason you can say "20::Double" is that in Haskell an integer literal has type "Num a => a", meaning it can be any numeric type you like.

You are correct that a typeclass is a set of types. To be precise, it is the set of types that implement the functions in the "where" clause of the typeclass. Your type signature for your numToDouble correctly expresses what you want to do.

All you know about a value of type "n" in your function is that it implements the Num interface. This consists of +, -, *, negate, abs, signum and fromInteger. The last is the only one that does type conversion, but its not any use for what you want.

Bear in mind that Complex is also an instance of Num. What should numToDouble do with that? The Right Thing is not obvious, which is part of the reason you are having problems.

However lower down the type hierarchy you have the Real typeclass, which has instances for all the more straightforward numerical types you probably want to work with, like floats, doubles and the various types of integers. That includes a function "toRational" which converts any real value into a ratio, from which you can convert it to a Double using "fromRational", which is a function of the "Fractional" typeclass.

So try:

toDouble :: (Real n) => n -> Double
toDouble = fromRational . toRational

But of course this is actually too specific. GHCI says:

Prelude> :type fromRational . toRational
fromRational . toRational :: (Fractional c, Real a) => a -> c

So it converts any real type to any Fractional type (the latter covers anything that can do division, including things that are not instances of Real, like Complex) When messing around with numeric types I keep finding myself using it as a kind of generic numerical coercion.

Edit: as leftaroundabout says,

realToFrac = fromRational . toRational

这篇关于输入数字的签名加倍?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆