0votos

notación posfija en Haskell

por josejuan hace 1 año

Compilando dinámicamente (en tiempo de ejecución) y polivariádica.

realizar algoritmo que calcule el resultado de cualquier notación posfija dada

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, RankNTypes #-} 
import Data.List (nub) 
import Data.Map (Map, (!), fromList) 
import qualified Data.Map as M 
 
bin = [("+", (+)), ("-", (-)), ("*", (*)), ("/", (/))] 
una = [("cos", cos), ("sin", sin)] 
 
compile :: [String] ->([String], Map String Double ->Double) 
compile = c [] [] 
  where c vs qs (x:xs) = case (qs, reads x, x `lookup` bin, x `lookup` una) of 
                           (     _, [(v, "")],   _,   _) ->c    vs  ((\_ ->            v):qs) xs 
                           (a:b:gs,         _, Just f,   _) ->c    vs  ((\m ->f (b m) (a m)):gs) xs 
                           (a:  gs,         _,   _, Just f) ->c    vs  ((\m ->      f (a m)):gs) xs 
                           (     _,         _,   _,   _) ->c (x:vs) ((\m ->          m!x):qs) xs 
        c vs (a:_)  _  = (nub vs, a) 
 
-- Ya está. 
 
 
 
 
-- Si se quiere interpretar: 
play eq vs = f $ fromList $ zip vn vs where (vn, f) = compile $ words eq 
 
 
 
 
-- Si se quiere hacer polivariádica (que no suele ser la forma recomendada en Haskell): 
class Run a r | r ->a where 
  run' :: String ->[a] ->a ->r 
 
instance Run Double Double where 
  run' eq xs x = play eq $ reverse (x:xs) 
 
instance Run a r =>Run a (a ->r) where 
  run' eq xs x y = run' eq (x:xs) y 
 
run :: forall r a . Run a r =>String ->a ->r 
run eq = run' eq [] 
 
{- 
 
> run "3 y + x *" 3.0 2.0 :: Double 
15.0 
 
> run "x cos y * z 5 +" pi 4.0 1.0 :: Double 
8.141592653589793 
 
 
 
-} 

Comenta la solución

Tienes que identificarte para poder publicar tu comentario.