Recursion 如何使用';getChar';?

Recursion 如何使用';getChar';?,recursion,idris,Recursion,Idris,有人能帮我吗 这是我所追求的数据结构: example : (n : Nat ** Vect n (n1 : Nat ** Vect n1 Char)) example = (3 ** [(3 ** ['a', 'b', 'c']), (3 ** ['d', 'e', 'f']), (3 ** ['g', 'h', 'i'])]) 我想从STDIN中读取字符,并为每\n行创建一个包含该行字符的新向量。一个空行结束递归 这将是上述示例的输入: abc\n def\n ghi\n \n 我想知道

有人能帮我吗

这是我所追求的数据结构:

example : (n : Nat ** Vect n (n1 : Nat ** Vect n1 Char))
example = (3 ** [(3 ** ['a', 'b', 'c']), (3 ** ['d', 'e', 'f']), (3 ** ['g', 'h', 'i'])])
我想从STDIN中读取字符,并为每\n行创建一个包含该行字符的新向量。一个空行结束递归

这将是上述示例的输入:

abc\n
def\n
ghi\n
\n
我想知道一个递归函数是否可行。对于整个字符串,如下所示:

read_vect : IO (len ** Vect len String)
read_vect = do x <- getLine
               if (x == "")
                  then pure (_ ** [])
                  else do (_ ** xs) <- read_vect
                          pure (_ ** x :: xs)
读取向量:IO(len**vect len String)

read_vect=do x您在
示例中的类型与
列表(List Char)
同构,因为您可以这样做

listToVect : List a -> (n : Nat ** Vect n a)
listToVect xs = (length xs ** fromList xs)

vectToList : (n : Nat ** Vect n a) -> List a
vectToList (_ ** xs) = toList xs
所以我们可以用
列表
的形式来编写它:

lines : List Char -> List (List Char)
lines = foldr step []
  where
    step : Char -> List (List Char) -> List (List Char)
    step '\n' ls = [] :: ls
    step c [] = [[c]]
    step c (l::ls) = (c::l) :: ls

lines' : String -> (n : Nat ** Vect n (n' : Nat ** Vect n' Char))
lines' = listToVect . map listToVect . lines . unpack
然而,我不相信这是你想要的。

字符矩阵不是
List(List Char)
,对于某些固定的
n
m
,它是一个
Vect n(Vect m Char)
,因为它是一个矩阵的全部要点是所有行的长度都相同

我们可以将其作为

Matrix : Nat -> Nat -> Type -> Type
Matrix n m a = Vect n (Vect m a)
然后写一些东西来解析给定大小的矩阵:

parseLine : (m : Nat) -> List Char -> Maybe (Vect m Char, List Char)
parseLine Z ('\n'::cs) = Just ([], cs)
parseLine (S m) (c :: cs) = map (\(l, cs') => (c::l, cs')) $ parseLine m cs
parseLine _ _ = Nothing

parseMatrix' : (n : Nat) -> (m : Nat) -> List Char -> Maybe (Matrix n m Char, List Char)
parseMatrix' Z m ['\n'] = Just ([], [])
parseMatrix' (S n) m cs = case parseLine m cs of
  Nothing => Nothing
  Just (l, cs') => case parseMatrix' n m cs' of
    Nothing => Nothing
    Just (ls, cs'') => Just (l::ls, cs'')
parseMatrix' _ _ _ = Nothing

parseMatrix : (n : Nat) -> (m : Nat) -> String -> Maybe (Matrix n m Char)
parseMatrix n m = map fst . parseMatrix' n m . unpack
这仍然不是您想要的,因为
n
m
是预先确定的,而不是查看输入;所以也许我们应该一起去

SomeMatrix : Type -> Type
SomeMatrix a = (n ** (m ** Matrix n m a))
导致

parseSomeMatrix : String -> Maybe (SomeMatrix Char)
parseSomeMatrix cs = case map unpack (lines cs) of
    l::ls => parseFrom l ls
    [] => Just (0 ** (0 ** []))
  where
    parseFrom : List Char -> List (List Char) -> Maybe (SomeMatrix Char)
    parseFrom cs ls = map (\vs => (length vs ** (m ** fromList vs))) (parseInto ls)
      where
        m : Nat
        m = length cs

        parseInto : List (List Char) -> Maybe (List (Vect m Char))
        parseInto [] = Just []
        parseInto (l :: ls) with (decEq (length l) m)
          | Yes p = map (\vs => (replace {P = \m => Vect m Char} p (fromList l)) :: vs) (parseInto ls)
          | No _ = Nothing

编辑,
getLine
:不需要实际的矩阵,这很简单:

read_structure : IO (k : Nat ** Vect k (l : Nat ** Vect l Char))
read_structure = do str <- getLine
                    let chrs = unpack str
                    let x = fromList chrs
                    if length chrs == 0
                       then pure (_ ** [])
                       else do (_ ** xs) <- read_structure
                               pure (_ ** (_ ** x) :: xs)
编辑,
getChar
:如果您真的想使用
getChar
进行递归,下面是一个版本,当使用
read\u list True
包装时,将获得一个
列表(list Char)
break
参数用于确定一行中是否有两个
'\n'

read_list : Bool -> IO (List (List Char))
read_list break = do chr <- getChar
                     if chr == '\n'
                        then if break
                                then pure []
                                else do rest <- read_list True
                                        pure ([] :: rest)
                        else do rest <- read_list False
                                case rest of
                                     x :: xs => pure ((chr :: x) :: xs)
                                     Nil => pure ([chr] :: Nil)

List
版本显然更具可读性,正如Cactus所指出的那样,
List a
k**Vect ka
相当。因此,您可以先解析它,然后转换为
Vect
s。

您真的想要
(n:Nat**vectn(n1:Nat**vectn1char))
而不是
(n:Nat**n1:Nat**vectn(vectn1-Nat))
?前者允许
示例=(2**[(2**['f','o']),(1**['o'])
,我不会调用矩阵。是的,我确实想要
(n:Nat**Vect n(n1:Nat**Vect n1 Char))
。我用“矩阵”这个词犯了一个错误。我用问题标题中的“结构”一词代替了它。我想逐行逐字地重复这些字符。但是这些线都有不同的长度。因此,这确实不是一个矩阵。如果它真的是一个矩阵,你的答案看起来很好!我真的很抱歉给您带来困惑,但您能再提一个建议吗?我添加了另一个解决方案。:-)我希望
getChar
不是强制性的?这将使它变得更复杂…沙什,我还在测试,但它似乎足够快,像这样。非常感谢你的回答!
read_list : Bool -> IO (List (List Char))
read_list break = do chr <- getChar
                     if chr == '\n'
                        then if break
                                then pure []
                                else do rest <- read_list True
                                        pure ([] :: rest)
                        else do rest <- read_list False
                                case rest of
                                     x :: xs => pure ((chr :: x) :: xs)
                                     Nil => pure ([chr] :: Nil)
read_vects : Bool -> IO (k : Nat ** Vect k (l : Nat ** Vect l Char))
read_vects break = do chr <- getChar
                      if chr == '\n'
                        then if break
                                then pure (_ ** [])
                                else do (_ ** rest) <- read_vects True
                                        pure (_ ** (_ ** []) :: rest)
                        else do (_ ** rest) <- read_vects False
                                case rest of
                                     (_ ** x) :: xs => pure (_ ** (_ ** (chr :: x)) :: xs)
                                     Nil => pure (_ ** (_ ** [chr]) :: Nil)