Есть ли в Haskell хороший способ написать функцию преобразования num в num `toNum :: (Num a, Num b) => a -> b`? - PullRequest
6 голосов
/ 23 июля 2011

Например, один плохой способ состоит в том, чтобы перебирать строку:

toReadableNum :: (Num a, Num b, Read b) => a -> b
toReadableNum = read . show

Если нет хороших способов, есть ли другие плохие способы?Реализация конкретная?Требуется расширение языка?

Ответы [ 4 ]

8 голосов
/ 23 июля 2011

Вы не можете (разумно) перейти от Num к Num, поскольку Num не предоставляет механизма для извлечения информации о значении, которое хранится, кроме его ложных уравнений и шоу-машин, но если вы готовы принять немного больше от имени номера, с которого вы приходите, тогда вы можете обратиться за помощью.

В частности

fromIntegral :: (Integral a, Num b) => a -> b

и состав

toRational :: Real a => a -> Rational

с

fromRational :: Fractional a => Rational -> a

оба являются хорошими кандидатами на то, что вы имеете в виду, если не совсем то, что вы просили.

В то время как read . show хорошо напечатан и имеет подпись, которую вы предлагаете, значение имеет значение gobbledigook. Ничто не говорит о том, что текст, выданный одним экземпляром Show, будет совместим с совершенно другим экземпляром Read, и существует множество встречных примеров.

(подразумеваемый) контракт на Read и Show применяется только тогда, когда вы используете их с тем же типом!

7 голосов
/ 23 июля 2011

Хороших путей нет.Некоторые числа содержат больше информации, чем другие, так как вы можете рассчитывать на хорошее преобразование между двумя произвольными числами.Несколько простых примеров: Как конвертировать Double в Int?Рационально чтобы на Int8?Сложный двойник до числа с плавающей точкой?

Все это влечет за собой потерю информации, и тогда нет очевидного правильного пути.


И, как говорит @hammar, операции в Num просто не работаютне позволяют вам построить такую ​​функцию.

3 голосов
/ 23 июля 2011

Вы не можете написать какую-либо полезную функцию типа (Num a, Num b) => a -> b.Поскольку a и b являются переменными типа, единственными полезными операциями, которые мы можем использовать над ними, являются операции в классе Num.(Eq и Show здесь не сильно нам помогут).

class  (Eq a, Show a) => Num a  where
    (+), (-), (*)       :: a -> a -> a
    negate              :: a -> a
    abs                 :: a -> a
    signum              :: a -> a
    fromInteger         :: Integer -> a

Единственная функция, которая позволяет вам сделать b, если у вас не было того, с чего начатьfromInteger, но у вас нет возможности превратить a в Integer, поэтому единственные функции, которые вы можете написать этого типа, возвращают fromInteger некоторой константы или дна.Не очень полезно.


Как указывало augustss , нет никакого очевидного способа сделать это преобразование в любом случае.Помните, что многие типы могут быть Num.Не только различные типы действительных чисел, но также и комплексные числа, матрицы, полиномы и т. Д. Между всеми ними нет значимого преобразования, которое бы работало.

0 голосов
/ 23 июля 2011

Хороший способ заключается в том, чтобы сделать определенный вид преобразования, например, круглый или зажим.Такая функция делает то, что говорит.

...