Haskell 如何使一个参数成为另一个参数类型的函数?
我在写,Haskell 如何使一个参数成为另一个参数类型的函数?,haskell,types,Haskell,Types,我在写,?(x)。代码如下所示: -- Minkowski's question-mark function import Data.Ratio mink' :: (Ord a,RealFrac a) => a -> a -> a mink' toler x | toler > 1 = x | x == 0 = x | x < 0 = (-mink' toler (-x)) | x >= 1 = (mink' toler (x-1)) +1
?(x)
。代码如下所示:
-- Minkowski's question-mark function
import Data.Ratio
mink' :: (Ord a,RealFrac a) => a -> a -> a
mink' toler x
| toler > 1 = x
| x == 0 = x
| x < 0 = (-mink' toler (-x))
| x >= 1 = (mink' toler (x-1)) +1
| otherwise = (2 ^^ (-intpart))* (2- mink' (toler/x^2) fracinvx )
where
invx=1/x
intpart=floor invx
fracinvx=invx-fromIntegral intpart
-- mink :: (Num a,Floating a,RealFrac a) => a -> a
-- mink x = (mink' toler fracx) + intx
-- where
-- intx = fromIntegral (round x)
-- fracx = x-intx
-- (_,ex) = decodeFloat (1::a)
-- toler = 2^^ex
mink :: (Num a,RealFrac a) => a -> a
mink x = (mink' 0 fracx) + intx
where
intx = fromIntegral (round x)
fracx = x-intx
(?(1/φ)==2/3
准确,但函数在那里非常陡峭。)
如何使toler
取决于x
的类型
如何使toler
取决于x
的类型
使值依赖于类型的机制是类型类。例如,您可以将mink
作为一种方法:
class (Num a, RealFrac a) => Minkowski a where
mink :: a -> a
instance Minkowski Rational where -- this will want `-XFlexibleInstances`
mink x = (mink' 0 fracx) + intx where ...
instance Minkowski Double where
mink x = (mink' 1e-40 fracx) + intx where ...
要根据解码浮点
自动确定ε,您的方法实际上非常有效。问题在于不能在函数体中使用Haskell 98样式签名的a
,这需要-XScopedTypeVariables
:
{-# LANGUAGE ScopedTypeVariables, UnicodeSyntax #-}
minkFloating :: ∀ a . (Num a,Floating a,RealFrac a) => a -> a
minkFloating x = (mink' toler fracx) + intx
where
intx = fromIntegral (round x)
fracx = x-intx
(_,ex) = decodeFloat (1::a)
toler = 2^^ex
那么您正在创建一个名为
Minkowski
的新类型类?不应该有专门针对Double
的实例,但是对于任何浮动
,其中toler
是类型的ulp,我尝试在注释掉的代码中执行该操作,但无法使其工作。1e-40太精确了,我明白了。请参见编辑。虽然我必须在minkFloating
的类型签名中添加RealFloat a
,但这很有效。
{-# LANGUAGE ScopedTypeVariables, UnicodeSyntax #-}
minkFloating :: ∀ a . (Num a,Floating a,RealFrac a) => a -> a
minkFloating x = (mink' toler fracx) + intx
where
intx = fromIntegral (round x)
fracx = x-intx
(_,ex) = decodeFloat (1::a)
toler = 2^^ex
instance Minkowski Double where mink = minkFloating
instance Minkowski Float where mink = minkFloating