2010-07-03 39 views
0

好的,这一次我要说清楚,function1的工作是检查一个字符串是否出现'?'事情,他会把剩下的字符串放在一个列表中。如果不是,它将一切都存储在堆栈,我怎么能做到这一点在Haskell中的表中存储数据

function2 :: [String] -> [([Char], [Integer]->[Integer])] 
function1 :: [String] -> [Integer] -> ([Integer], String) 
function1 [] stack = (stack, "") 
function1 (x:xs) stack 
    | x == "?"   = function2 xs -- # map the tokens after '?' to functions 
              -- # and put them into dictionary for 
              -- # function1's later use 
    | x == "m"   = function1 xs ((read x :: b):stack) 
    | x == isJust lookup = eval xs (f stack) 
    ... 
    where lookup = -- # lookup(f) is the function that is mapped from the token x 
+1

如果你想让你的函数返回一个不同的类型,然后让它返回一个不同的类型。如果'function2'没有返回'b',那么你需要编写一个函数来将'function2'的输出转换为'b'类型的东西,然后将它应用到'function2'。 – jrockway 2010-07-03 05:19:30

+0

不,不,不必,有一些方法可以绕过这个返回,就像在函数2中写一些会返回b的东西,但是函数2仍然会自己完成 – Rn2dy 2010-07-03 05:27:59

+3

的工作,这正是Jrockway提出的。只需用'function3 x = SomeB'写一个'function3 :: a - > b',并在第一个函数中使用'function3(function2 xs)'。 – tonio 2010-07-03 06:16:17

回答

4

首先,请使用Data.Map存储字典而不是元组列表以避免O(N)查找。

Haskell函数是纯粹的,即你不应该有可变的状态。如果您需要“存储”某些内容,它必须出现在参数列表中,例如

import qualified Data.Map as M 

type Stack = [Integer] 
type StackFunction = Stack -> Stack 
type Token = String 
type TokenMap = M.Map Token StackFunction 
function2 :: [Token] -> TokenMap 

function1_alt :: TokenMap -> [Token] -> Stack -> (Stack, Token) 
function1_alt _ [] stack = (stack, "") 
function1_alt map ("?":xs) stack = let newMap = function2 xs in 
             function1_alt (M.union oldMap newMap) xs stack 
-- #   pass the new changed map as an argument ^^^^^^^^^^^^^^^^^^^^^ 
function1_alt map ("m":xs) stack = function1_alt map xs ((read x):stack) 
function1_alt map (x:xs) stack | isJust f = eval xs (fromJust f $ stack) 
           | otherwise = ... 
           where f = M.lookup x map 

function1 :: [Token] -> Stack -> (Stack, Token) 
function1 = function1_alt M.empty 

另外,还可以使用一元之类的东西Data.STRefData.IORef使用可变的变量,但随后需要在ST或IO单子被包裹不必要的代码的某些部分。

+0

是的,这正是我需要做的,非常感谢你! – Rn2dy 2010-07-03 20:25:32

1

Appparently要投一个String([字符])弄成|什么。这是行不通的。形式上的原因:fun :: a-> b是不可能的,因为b必须在参数的某处出现,否则它不能被扣除。非正式地:你不能保证类型安全。例如:你的[Char] ==“Hello world”,你试图将它转换成Int。 顺便说一句cast是C语言为typeconversion。

1

问题是,如果x =='?',用你写的方式,function1将返回与function2相同的值。如果function2没有返回,那么function1会这样做。

既然很难推断出你想要做什么,那么简短的回答就是不!

但是不要放弃!在任何情况下,你都可以做的事情实际上相当不错。首先,如果你只想知道函数2返回什么,并且在 的情况下x是'?'返回别的东西FUNCTION1你这样做:

function1 (x:xs) 
      | x == '?' = somethingElse 
      | x == '3' = do something with fun2Returns   
     ... 

    where fun2Returns = function2 xs 

现在,让我们说你要那个不返回(在C-讲这就是return null)任何东西,你必须要明确有关,在你的类型,通过使用Maybe类型。

function1 :: String -> Maybe b 
function1 (x:xs) 
      | x == '?' = Nothing 
1

有点像?

function1 :: [Char] -> b 
function1 (x:xs) 
    | x == '?' && isJust r = fromJust r where r = function2 xs 

function2 :: [Char] -> Maybe b 

更新:

这看起来不正确(x :: String,但不是Maybe a

... 
| x == isJust lookup = eval xs (f stack) 
... 
where lookup = -- # lookup(f) is the function that is mapped from the token x 

我想这应该是这个样子:

... 
| maybe False (x ==) lookup = eval xs (f stack) 
...