Surutilisation de fromIntegral à Haskell

chaque fois que j'écris une fonction en utilisant des doubles et des entiers, je trouve ce problème où je dois constamment utiliser "frommintegral" partout dans ma fonction. Par exemple:

import Data.List

roundDouble
    :: Double
    -> Int 
    -> Double
roundDouble x acc = fromIntegral (round $ x * 10 ** fromIntegral acc) / 10 ** fromIntegral acc

y a-t-il une façon plus facile d'écrire ceci? (Je sais il peut y avoir des moyens plus faciles de l'arrondi d'un nombre et s'il vous plaît laissez-moi savoir! Cependant, je m'intéresse principalement à la façon d'éviter d'utiliser autant de "frommintegrals".)

Merci, Ash

27
demandé sur Don Stewart 2010-08-11 01:31:12

4 réponses

Parfois je trouve utile une fonction d'aide:

roundDouble x acc = (round $ x * 10 ^ acc) /. (10 ^ acc)
    where 
    x /. y = fromIntegral x / fromIntegral y

que la fonction helper peut également être écrit:

(/.) = (/) `on` fromIntegral

on est de Data.Function .

24
répondu luqui 2010-08-10 23:11:52

vous pouvez utiliser ^ au lieu de ** . ^ prend n'importe quelle intégrale comme deuxième argument, donc vous n'avez pas besoin d'appeler fromIntegral sur le deuxième opérande. Ainsi votre code devient:

roundDouble X acc = frommintegral (round $ x * 10 ^ acc) / 10 ^ acc

Qui n'a qu'un seul fromIntegral . Et celui que vous ne pouvez pas vous débarrasser comme round renvoie naturellement une intégrale et vous ne pouvez pas effectuer la division non-entière sur un Intégrante.

12
répondu sepp2k 2010-08-10 21:40:03

j'ai un problème similaire avec le code de composition, où fromIntegral est utilisé pour convertir CInt en Int. Je définis habituellement fI = fromIntegral pour le rendre plus facile. Vous pouvez également avoir besoin de lui donner une signature de type explicite ou utiliser-XNoMonomorphismRestriction.

si vous faites beaucoup de mathématiques, vous pourriez vouloir regarder le Prélude numérique , qui semble avoir des relations beaucoup plus sensées entre les différents types numériques.

6
répondu John L 2010-08-10 22:29:05

une autre idée, similaire à luqui . La plupart de mes problèmes avec fromIntegral sont liés à la nécessité de diviser Int par Double ou Double par Int . Ainsi ce (/.) permet de diviser deux Real types, pas nécessairement les mêmes, pas nécessairement Integral types comme dans la solution de luqui:

(/.) :: (Real a, Real b, Fractional c) => a -> b -> c
(/.) x y = fromRational $ (toRational x) / (toRational y)

exemple:

ghci> let (a,b,c) = (2::Int, 3::Double, 5::Int)
ghci> (b/.a, c/.a, a/.c)
(1.5,2.5,0.4)

il fonctionne pour deux Real s, mais je soupçonne que la division rationnelle et la conversion en/de Rational ne sont pas très efficaces.

maintenant votre exemple devient:

roundDouble :: Double -> Int -> Double
roundDouble x acc = (round $ x * 10 ^ acc) /. (10 ^ acc)
4
répondu sastanin 2017-05-23 11:53:44