import Html exposing (..)
import String
type alias Stack = List String
push : String -> Stack -> Stack
push tok stack =
(tok :: stack)
pop : Stack -> (Maybe String, Maybe Stack)
pop stack =
let
top = List.head stack
in
(top, List.tail stack)
reverseString: String -> String
reverseString incoming =
let
stringStack = incoming
|> String.split ""
|> List.foldl push []
in
-- How to use pop() here?
List.foldr String.append "" stringStack
main : Html
main =
"Hello World!"
|> reverseString
|> toString
|> text
我正在使用reverse
和push()
尝试使用我自己的pop()
字符串。我可以合并push
,但无法在函数pop
中使用reverseString
。我在这里做错了什么?
答案 0 :(得分:2)
你正试图用你的Stack ADT List.foldr
,但这是作弊;如果Stack真的是一个ADT,我们应该无法利用它的列表!
List.foldr
也很难匹配Stack ADT,因为它释放了它的函数参数来处理空列表,而pop
函数强制我们同时处理非空和空栈的情况
如果我们想要一个Stack ADT,我们必须手动通过堆栈进行递归,而不使用List.foldr
。首先,减少pop
函数以更简洁地表示“空堆栈”和“非空堆栈”这两种情况将会很方便:
pop : Stack -> Maybe (String, Stack)
pop stack =
case stack of
[] -> Nothing
x :: xs -> Just (x, xs)
然后我们可以制定reverseString
reverseString : String -> String
reverseString string =
let
loop stack =
case pop stack of
Nothing -> ""
Just (symbol, stack') -> symbol ++ loop stack'
in
String.split "" string -- Split the string into a list
|> List.foldl push [] -- Push each letter on the stack
|> loop -- Pop each letter off the stack
直接使用列表可能更容易。然后Cons (::)
是推,List.foldl
是通过弹出直到空来减少堆栈的函数。
reverseString2 : String -> String
reverseString2 =
String.split "" -- "String -> Stack" (implicitly pushes)
>> List.foldl (::) [] -- "Stack -> List" (reduces the stack)
>> String.join "" -- "List -> String" (nothing to do with stacks)
答案 1 :(得分:1)
Elm没有在语言级别进行迭代,因此您需要使用支持迭代和映射的数据结构。在这种情况下,我认为懒惰列表可能是最好的,因为你不会通过递归来破坏堆栈。
在这种情况下,stackIterator从堆栈中生成一个惰性的字符串列表。为了得到我们想要的惰性值序列,我们需要一个可以重复应用于它自己的结果的函数,并且因为pop返回一个head,stack的元组,该函数是((mhd,tl) - > pop TL)。下一部分作为管道运行,首先拉出元组的左侧部分,第二部分承诺如果返回的堆栈顶部为Nothing则终止列表,第三部分,通过{{1将Maybe
的列表转换为字符串}}
通过替换LL.foldr和惰性列表,您的堆栈上有一个适当的非递归迭代,涉及您的pop函数。
一些风格笔记:
我自己的榆树风格并不完美。可能有一种聪明的方法来撰写Maybe.withDefault
和snd
,并不需要明确的lambda绑定。
pop
答案 2 :(得分:0)
FWIW,我修改了Rundberget's version以使用String作为堆栈。虽然它不像其他解决方案那样通用,但它不使用List.foldr
或List.foldl
,最终会更短。
module SStack where
import String
type alias SStack = String
empty : SStack
empty =
""
push : String -> SStack -> SStack
push tok stacks =
tok ++ stacks
pop : SStack -> Maybe (Char, SStack)
pop stacks =
String.uncons stacks
reverse : SStack -> SStack
reverse stack =
case (pop stack) of
Nothing ->
empty
Just(x, r) ->
push (reverse r) (String.fromChar x)
这里是驱动程序模块:
import SStack as Stack exposing (..)
import Html exposing (..)
reverseString : String -> String
reverseString str =
Stack.reverse str
main : Html.Html
main =
reverseString "Hello World !"
|> Html.text