首页 > 解决方案 > 是否可以将嵌套列表返回为 IO()

问题描述

我有一些简单的函数,我需要 makeMove 来返回 IO():

toPole :: Show a => [a] -> [a] -> String
toPole fpole spole = show(head fpole:spole)

fromPole :: Show a => [a] -> String
fromPole fpole = show (tail fpole)

makeMove :: [a] -> [a] -> IO ()
makeMove [] _ = return ()
makeMove fpole spole = putStr (unwords p)
     where p = [fromPole fpole, toPole fpole spole]

这个想法是我有两个列表,我想将列表的第一项移动fpole到第二个列表spole,并将它们打印为嵌套列表[[],[]]putStr有没有办法做到这一点?我用 and 的返回类型尝试了不同的东西toPolefromPole但认为如果返回类型是 . 将 makeMove 转换为 IO() 会更容易String

我得到的错误来自fromPole fpolewhere p = [fromPole fpole, ...

No instance for (Show a) arising from a use of ‘fromPole’

标签: haskell

解决方案


makeMove也需要Show a约束。就目前而言,您是说makeMove可以接受任何类型的列表作为参数,但随后您尝试将那些可能Show较少的值传递给fromPole.

makeMove :: Show a => [a] -> [a] -> IO ()
makeMove [] _ = return ()
makeMove fpole spole = putStr (unwords p)
     where p = [fromPole fpole, toPole fpole spole]

更简洁的实现不会对列表元素进行任何假设toPole或做出任何假设;fromPole事实上,它们几乎没有必要。没有它们,您可以定义makeMove(可以说更清楚)。

transfer :: [a] -> [a] -> ([a], [a])
transfer (x:xs) ys = (xs, (x:ys))

makeMove :: Show a => [a] -> [a] -> String
makeMove fpole spole = let (fpole', spole') = transfer fpole spole
                       in unwords [fpole', spole']

showMove :: Show a => [a] -> [a] -> IO ()
showMove fpole spole = print (makeMove fpole spole)

在这里,我将函数分解为三个逻辑部分:

  1. transfer只需将元素从一个极点移动到另一个极点。
  2. makeMoveString从结果中创建一个transfer
  3. showMove输出移动的结果。

尽可能多的工作保存在纯函数中,只showMoveIO.


推荐阅读