在Haskell中,用户如何将项目添加到列表中
我了解如何使用递归数据结构来管理内容列表:在Haskell中,用户如何将项目添加到列表中,haskell,Haskell,我了解如何使用递归数据结构来管理内容列表: data Thingy a = NoThingy | Thingy a a (Thingy a) deriving (Show, Read) firstThingsFirst :: a -> a -> (Thingy a) firstThingsFirst a b = Thingy a b NoThingy andAnotherThing :: a -> a -> Thingy a -> Thingy a andAno
data Thingy a = NoThingy | Thingy a a (Thingy a) deriving (Show, Read)
firstThingsFirst :: a -> a -> (Thingy a)
firstThingsFirst a b = Thingy a b NoThingy
andAnotherThing :: a -> a -> Thingy a -> Thingy a
andAnotherThing a b NoThingy = Thingy a b NoThingy
andAnotherThing a b things = Thingy a b things
在ghci中,我可以做如下事情:
let x=andAnotherThing "thing1" "thing2" NoThingy
let y=andAnotherThing "thing3" "thing4" x
import System.IO
allThings=NoThingy
main = do
putStrLn "First Thing"
first<-getLine
putStrLn "Second Thing"
second<-getLine
let allThings=Thingy first second allThings
print allThings
main
let allThings = Thingy (read first :: Int) (read second :: String) allThings
然而,我不知道如何使这项工作为一个编译程序,需要用户输入。换句话说,我想让用户填充结构。比如:
let x=andAnotherThing "thing1" "thing2" NoThingy
let y=andAnotherThing "thing3" "thing4" x
import System.IO
allThings=NoThingy
main = do
putStrLn "First Thing"
first<-getLine
putStrLn "Second Thing"
second<-getLine
let allThings=Thingy first second allThings
print allThings
main
let allThings = Thingy (read first :: Int) (read second :: String) allThings
import System.IO
万物=虚无
main=do
putStrLn“第一件事”
首先听起来像是在寻求一种方法,将用户输入的String
类型转换为Thingy
类型的值。由于您的Thingy
类型已经有了Read
的实例,您可以使用Read
功能:
read :: Read a => String -> a
这使您的main
功能更像:
main = do
putStrLn "First Thing"
first <- getLine
putStrLn "Second Thing"
second <- getLine
let allThings = Thingy (read first) (read second) allThings
print allThings
main
另一个问题是,类型推断无法猜测要使用哪种类型a
,因此您还必须给出提示,例如:
let x=andAnotherThing "thing1" "thing2" NoThingy
let y=andAnotherThing "thing3" "thing4" x
import System.IO
allThings=NoThingy
main = do
putStrLn "First Thing"
first<-getLine
putStrLn "Second Thing"
second<-getLine
let allThings=Thingy first second allThings
print allThings
main
let allThings = Thingy (read first :: Int) (read second :: String) allThings
可能值得注意的是,在这个定义中,allThings
是一个无限的结构,并且将永远无法打印:最后一次调用main
将永远无法到达。您创建的是一个可以打印的无限自我引用的“allThings”
您将绑定到名称allThings两次。第一次在主屏幕前,第二次在打印前
第二个绑定指的是位于右侧末尾的所有内容。此引用不是对第一个绑定的引用。此引用指向第二个绑定本身
如果更改第二个装订和打印的名称:
main = do
putStrLn "First Thing"
first <- getLine
putStrLn "Second Thing"
second <- getLine
let allThings2 = Thingy (read first) (read second) allThings
print allThings2
main
main=do
putStrLn“第一件事”
首先,问题是您试图使用一个变量来保存可变状态(就像命令式语言中的变量一样),但在Haskell中无法这样做所有状态必须作为参数显式传递给函数。正如其他答案所指出的,main中的allThings
实际上是全局范围内的allThings
的一个单独变量(它只是隐藏相同的名称)
下面的示例演示如何构建一个程序,该程序在构建数字列表的同时始终循环。我认为这正是你想要做的事情,让它适应“东西”应该不难
在我们的例子中,我们必须为循环保留的状态是下一个要输入的数字(1、2等)的索引和我们已经读取的数字列表。因此,我们的循环函数将接收此状态作为参数,并返回IO操作
module Main where
-- Explicit signature so readLn and show don't complain...
loop_step :: (Int, [Int]) -> IO ()
loop_step (i,xs) = do
putStrLn ("Enter the " ++ show i ++ "th number:")
n <- readLn
let newList = n : xs
print newList
loop_step (i+1, newList)
main :: IO ()
main = do
loop_step (1, [])
modulemain其中
--显式签名,以便读取和显示,不要抱怨。。。
循环步骤::(Int,[Int])->IO()
循环_步骤(i,xs)=do
putStrLn(“输入“++显示i+”第个数字:”)
nHaskell中的值是不可变的,因此如果您“向列表中添加一项”,您将得到一个新列表。因此,在上面的代码中
let allThings = Thingy first second allThings
没有达到你的期望。顶级的allThings具有值NoThingy
,并且该值不能更改。let绑定中的名称allThings
不引用顶级实体,它引入了一个新的绑定来隐藏顶级名称,并且该新名称也在绑定的右侧引用。
所以这条线和下面的是等价的
let theThings = Thingy first second theThings
print theThings
let绑定创建一个循环结构,将自身称为其组件之一。这当然意味着打印永远不会完成
您(可能)想要执行的操作需要将要更新的结构作为参数传递
loop things = do
putStrLn "First Thing"
...
let newThings = Thingy first second things
print newThings
loop newThings
当然,正如Nicolas所说,您可能希望将输入字符串转换为适当类型的值。的和的第一个子句是多余的,因为第二个子句做同样的事情。就这件事而言,和任何东西都是多余的,因为它和东西一样。谢谢所有回答的人。正如你们大多数人所说明的,创建一个循环并从main调用它正是我想要的。顺便说一下,您可以使用内置的[(a,a)]
而不是东西a
。