Haskell 递归函数中的类型匹配和IO问题

Haskell 递归函数中的类型匹配和IO问题,haskell,recursion,io,pattern-matching,type-mismatch,Haskell,Recursion,Io,Pattern Matching,Type Mismatch,我遇到了一些问题,找不到原因。我目前正在使用GHCi portable的最新版本,但面对现实:这是我第一次使用Haskell,所以像往常一样,问题可能是用户,而不是系统 出现的问题包括: 我不完全确定我得到了let x=0和xk->[(k,v)]->v之间的区别 findKey xs=snd。头过滤器(\(k,v)->key==k)$xs --检查给定状态是否在接受状态列表中 checkAcception::String->[String]->IO() checkAcception final

我遇到了一些问题,找不到原因。我目前正在使用GHCi portable的最新版本,但面对现实:这是我第一次使用Haskell,所以像往常一样,问题可能是用户,而不是系统

出现的问题包括:

  • 我不完全确定我得到了
    let x=0
    xk->[(k,v)]->v之间的区别
    findKey xs=snd。头过滤器(\(k,v)->key==k)$xs
    --检查给定状态是否在接受状态列表中
    checkAcception::String->[String]->IO()
    checkAcception finalState acceptingStates=do
    让accept=any(=finalState)接受状态
    如果接受
    然后putStrLn“输入已接受!!”
    else putStrLn“输入被拒绝!!”
    
    其想法是让用户选择一个文件,从中加载定义(
    readDef
    ,就像一个符咒)。然后提示他输入FSM工作的一些输入。
    递归的
    changeState
    然后执行实际工作(也不工作…。
    最后,显示状态和转换的顺序,并检查最终状态是否为接受状态(
    checkAcceptance


    现在,不要试图优化我所写的内容。我知道,定义建模的方式可以改进,我写的许多行可以使用一些高阶Haskell-foo编写得更短。但请帮我解决上面列出的问题(当然也请帮我解决问题)。
    先谢谢你


    最后一件事:我正在为我的大学的一个研讨会尝试一些Haskell,因此如果软件架构组的人在谷歌上搜索我的代码并阅读以下内容:Hi:)

    您只需将
    changeState
    函数的第二个子句更改为:

    changeState startState (x:xs) stateTransitions =
        let (currentState, oldStates) = changeState xs startState stateTransitions
            newState = findKey x (findKey currentState stateTransitions)
            oldStates2 = (oldStates ++ currentState ++ " -(" ++ [x] ++ ")-> ")
        in (newState, oldStates2)
    
    我们1)删除了do,2)组合了let子句,3)将第二个出现的oldState变量重命名为oldState2。在Haskell中,我们不重新定义变量——我们只是创建一个具有新名称的变量。完整的代码可在此处获得:

    当你写作时:

    (new, old) = changeState ...
    

    你是说changeState是一个纯函数。如果您使用
    do定义
    changeState
    。。。return(…)
    您是说它是一个一元计算,当您调用它时,您需要使用箭头
    问题是
    do
    表示法和
    return
    函数不做您认为它们做的事情。在Haskell中:
    return
    并不表示函数应该结束(即使它最常见于函数的结尾);它只是意味着参数应该被包装在一个
    Monad
    中。因为应用了所有参数的函数类型是(String,String),编译器认为您正在尝试使用以下内容:(在没有GHC扩展的情况下不会实际编译,如果使用,将抛出异常,因为我使用了
    未定义的

    但是编译器已经知道
    (String,String)->(String,String)
    a->(String,a)
    不匹配,因此它没有检查实例是否存在。 修复此问题会暴露出另一个问题:在同一个函数中定义两次
    oldStates
    ,除非这两个定义在不同的范围内,否则在Haskell中不起作用

    这是您的函数经过修改以正确编译,但我还没有对其进行测试

    changeState :: String -> String -> [(String, [(Char,String)])] -> (String, String)
    
    changeState startState [] _ = (startState, "")
    
    changeState startState (x:xs) stateTransitions = let
        (currentState, oldStates) = changeState xs startState stateTransitions
        newState = findKey x (findKey currentState stateTransitions)
        oldStates' = (oldStates ++ currentState ++ " -(" ++ [x] ++ ")-> ")
        in (newState, oldStates')
    

    请从头开始。写一个函数。确保它能够编译。测试一下。如果您遇到问题,请在此处询问有关一个函数的问题。然后继续下一步。在这里,你已经扔掉了一大堆乱七八糟的代码,并说“它不起作用。帮帮我。”没有太多人会有兴趣去挖掘所有这些。毫无疑问,你似乎在用字符串来表示LISP或Scheme程序员将使用符号的用途。在Haskell中,我们通常在可能的情况下尝试使用枚举类型。写一些类似于
    data FSMState=Start | Stop | A |…
    。然而,在Haskell中通常有更自然的FSM表示。@dfeur就像我没有想到的那样。。。我很清楚,我张贴的不是一个简明的问题。但我想我指出,我不确定问题产生于代码的哪一部分,所以我最好把它全部发布出来。最重要的是,我经常阅读一些帖子,其中一个过短的问题会导致更多的问题,因为上下文甚至意思都不清楚。因此,为了改进我的请求:我特别不确定
    changeState
    部分。问题依然存在:我对
    let的理解正确吗?是否有明显的类型不匹配是我造成的?递归的想法正确吗?不,
    changeState
    在我看来毫无意义。据我所知,你根本不需要/想要一个
    do
    块,我也不知道你说的“旧州”是什么意思。不是只有一个当前状态和一个下一个状态吗?是的,当然总是只有一个当前状态和一个下一个状态。但是,如果我想在命令行中打印正在使用的状态,即从开始状态到下一个状态的转换。。。到最后的状态,我看到两种方式:1。在递归函数中执行此操作。然后我需要将它定义为IO,但实际上我希望保持它的纯净。2.以递归方式构建一个字符串oldStates,我将随函数返回该字符串,稍后可以打印出来。
    (new, old) = changeState ...
    
    (new, old) <- changeState ...
    
    instance Monad ((,) String) where
      (>>=) = undefined :: (String,a) -> (a -> (String,b)) -> (String,b)
      return = undefined :: a -> (String,a)
    
    changeState :: String -> String -> [(String, [(Char,String)])] -> (String, String)
    
    changeState startState [] _ = (startState, "")
    
    changeState startState (x:xs) stateTransitions = let
        (currentState, oldStates) = changeState xs startState stateTransitions
        newState = findKey x (findKey currentState stateTransitions)
        oldStates' = (oldStates ++ currentState ++ " -(" ++ [x] ++ ")-> ")
        in (newState, oldStates')