Compile temporary code outside the haskell pattern?

Is it possible to create a function that overwrites the heckel code during compilation outside the quotes of the haskell pattern?

For instance:

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 

and at compile time, it converts g to:

 gx = (sin x, cos x) 

I would like my "differentiable" function to be passed to AST "f", and let me rewrite it before compiling. As far as I know, you cannot do this in the haskell template without passing it the full syntax of the function ie "g = differentiate sin".

thanks

+4
source share
2 answers

You are talking about macros, like in a diagram. The answer is no. Haskell functions must be “referentially transparent”, which means that if you give it two conditionally equal arguments, the results must be denotationally equal. I., every f must have

 f (1 + 1) = f 2 

And if f was a macro, that would not necessarily be so. However, this property is important for the "cleanliness" of the language - which makes Haskell so good as to reason and refactor.

However, Haskell has extensive work on automatic differentiation , none of which need a macro system - abstract modeling (and modeling to make it look good) is all that is needed.

+8
source

Theoretically, this is possible if you are ready to use your own set of mathematical functions and numbers. What you need to do is create a type system that tracks how each function is calculated. Then it will be reflected in the type of expression. Using either the haskell template and the reify function, or using the code of a type class, you can generate the correct code at compile time.

Here is an example of a hacked selection using type classes. It works with sin, cos, constants and addition. It would be a lot of work to implement a full range of operations. In addition, there is a fair bit of duplication in the code, if you plan to use this approach, you should try to fix this problem:

 {-# 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.+) ab 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 fx = sin x g = differentiate f hx = sin x + x + toNum 42 + x test1 = f . toNum test2 = g . toNum test3 = differentiate h . toNum 
+1
source

Source: https://habr.com/ru/post/1413065/


All Articles