English 中文(简体)
a. 在模板舱面范围外重写时间代码?
原标题:Compile time code rewriting outside of template haskell scope?

是否有可能在从模板中引出的纸面汇编时间时,形成一种重写法的功能?

例如:

differentiate :: Floating a => (a -> a) -> a -> (a,a)
differentiate = -- what goes here?

f :: Num a => a -> a
f = sin

g :: Num a => a -> (a,a)
g = differentiate f

并且,在编纂时,它会转化为:

g x = (sin x, cos x)

我希望我的“不同”职能能通过“f”的复兴,让我在汇编之前重新做。 只要我知道你不能在模板中这样做,就不必通过它来履行这一职能的全部内容,即“g = 区分罪”。

谢谢。

最佳回答

你们谈论的是宏观办法。 答案是没有的。 功能必须是“相对透明”的,这意味着如果你给它2个denotationally平等的论点,结果必须是平等的。 页: 1 必须

f (1 + 1) = f 2

如果<代码>f是宏观的,则不一定如此。 然而,这种财产对于语言的“纯洁性”至关重要——使Haskell如此理智和令人信服。

However, there is extensive work on automatic differentiation in Haskell, none of which needs a macro system -- abstract modeling (and typeclasses to make it look nice) are all that is necessary.

问题回答

如果你愿意使用自己的一套数学职能和号码,理论上是可能的。 你们需要做的是建立一个跟踪每项职能计算情况的类型系统。 这一点将反映在表述类型上。 如果使用模板的斜体和重整功能,或者使用类别代码,那么你可以在汇编正确代码时产生。

这里是使用类型分类的黑体样本。 它与罪 sin、 co、恒定和添加有关。 开展全套行动将有很多工作。 此外,如果你正在计划采用这种做法,那么守则中也有相当的重复之处,你应努力解决这个问题:

{-# LANGUAGE ScopedTypeVariables, UndecidableInstances, FlexibleInstances, MultiParamTypeClasses, FunctionalDependencies #-}
module TrackedComputation where
import Prelude hiding (sin, cos, Num(..))
import Data.Function (on)
import qualified Prelude as P    

-- A tracked computation (TC for short).
-- It stores how a value is computed in the computation phantom variable
newtype TC newComp val = TC { getVal :: val }
    deriving (Eq)

instance (Show val) => Show (TC comp val) where
    show = show . getVal


data SinT comp = SinT
data CosT comp = CosT

data AddT comp1 comp2 = AddT

data ConstantT = ConstantT

data VariableT = VariableT

sin :: (P.Floating a) => TC comp1 a -> TC (SinT comp1) a
sin = TC . P.sin . getVal
cos :: (P.Floating a) => TC comp1 a -> TC (CosT comp1) a
cos = TC . P.cos . getVal

(+) :: (P.Num a) => TC comp1 a -> TC comp2 a -> TC (AddT comp1 comp2) a
(TC a) + (TC b) = TC $ (P.+) a b

toNum :: a -> TC ConstantT a
toNum = TC

class Differentiate comp compRIn compROut | comp compRIn -> compROut where
    differentiate :: P.Floating a => (TC VariableT a -> TC comp a) -> (TC compRIn a -> TC compROut a)


instance Differentiate ConstantT compIn ConstantT where
    differentiate _ = const $ toNum 0

instance Differentiate (SinT VariableT) compIn (CosT compIn) where
    differentiate _ = cos
instance Differentiate VariableT compIn (ConstantT) where
    differentiate _ = const $ toNum 1

instance (Differentiate add1 compIn add1Out, Differentiate add2 compIn add2Out) =>
    Differentiate (AddT add1 add2) compIn (AddT add1Out add2Out) where
    differentiate _ (val :: TC compROut a) = result where
        first = differentiate (undefined :: TC VariableT a -> TC add1 a) val :: TC add1Out a
        second = differentiate (undefined :: TC VariableT a -> TC add2 a) val :: TC add2Out a
        result = first + second

instance P.Num val => P.Num (TC ConstantT val) where
    (+) = (TC .) . ((P.+) `on` getVal)
    (*) = (TC .) . ((P.*) `on` getVal)
    abs = (TC) . ((P.abs) . getVal)
    signum = (TC) . ((P.signum) . getVal)
    fromInteger = TC . P.fromInteger

f x = sin x

g = differentiate f

h x = sin x + x + toNum 42 + x

test1 = f . toNum
test2 = g . toNum
test3 = differentiate h . toNum




相关问题
Euler Problem in Haskell -- Can Someone Spot My Error

I m trying my hand at Euler Problem 4 in Haskell. It asks for that largest palindrome formed by multiplying two three-digit numbers. The problem was simple enough, and I thought my Haskell-fu was up ...

How does foldr work?

Can anybody explain how does foldr work? Take these examples: Prelude> foldr (-) 54 [10, 11] 53 Prelude> foldr (x y -> (x+y)/2) 54 [12, 4, 10, 6] 12.0 I am confused about these executions....

Efficient queue in Haskell

How can I efficiently implement a list data structure where I can have 2 views to the head and end of the list, that always point to a head a tail of a list without expensive calls to reverse. i.e: ...

Problem detecting cyclic numbers in Haskell

I am doing problem 61 at project Euler and came up with the following code (to test the case they give): p3 n = n*(n+1) `div` 2 p4 n = n*n p5 n = n*(3*n -1) `div` 2 p6 n = n*(2*n -1) p7 n = n*(5*n -3)...

Ways to get the middle of a list in Haskell?

I ve just started learning about Functional Programming, using Haskel. I m slowly getting through Erik Meijer s lectures on Channel 9 (I ve watched the first 4 so far) and in the 4th video Erik ...

haskell grouping problem

group :: Ord a => [(a, [b])] -> [(a, [b])] I want to look up all pairs that have the same fst, and merge them, by appending all the list of bs together where they have the same a and discarding ...

Closest equivalent to subprocess.communicate in Haskell

I want to do a popen() / python s subprocess.communicate from Haskell - start a program, give it stdin, and get its stdout/stderr. What s the most direct / Haskellish way to do this?