我试图将卡迪纳的一个例子转化为伊德里斯- 一种带有依赖型 纸张的语言.
这是我到目前为止:
PrintfType : (List Char) -> Type
PrintfType Nil = String
PrintfType ('%' :: 'd' :: cs) = Int -> PrintfType cs
PrintfType ('%' :: 's' :: cs) = String -> PrintfType cs
PrintfType ('%' :: _ :: cs) = PrintfType cs
PrintfType ( _ :: cs) = PrintfType cs
printf : (fmt: List Char) -> PrintfType fmt
printf fmt = rec fmt "" where
rec : (f: List Char) -> String -> PrintfType f
rec Nil acc = acc
rec ('%' :: 'd' :: cs) acc = \i => rec cs (acc ++ (show i))
rec ('%' :: 's' :: cs) acc = \s => rec cs (acc ++ s)
rec ('%' :: _ :: cs) acc = rec cs acc -- this is line 49
rec ( c :: cs) acc = rec cs (acc ++ (pack [c]))
Run Code Online (Sandbox Code Playgroud)
我使用的List Char,而不是String为格式,以便于与模式匹配为我赶紧跑进复杂性与模式匹配的参数String.
不幸的是我收到一条错误信息,我无法理解:
Type checking ./sprintf.idr
sprintf.idr:49:Can't unify PrintfType (Prelude.List.:: '%' (Prelude.List.:: t cs)) with PrintfType cs
Specifically:
Can't convert PrintfType (Prelude.List.:: '%' (Prelude.List.:: t cs)) with PrintfType cs
Run Code Online (Sandbox Code Playgroud)
如果我注释掉所有的模式匹配的情况下与3个元素(那些用'%' :: ...)中PrintfType和printf,然后将代码编译(但显然没有做什么有趣的事).
如何修复我的代码以便printf "the %s is %d" "answer" 42有效?
huy*_*hjl 14
在定义模式重叠的函数时(例如重叠的函数),似乎idris中存在一些当前的限制.经过多次尝试,我终于想出了一个解决方法:'%' :: 'd'c :: cs
data Format = End | FInt Format | FString Format | FChar Char Format
fromList : List Char -> Format
fromList Nil = End
fromList ('%' :: 'd' :: cs) = FInt (fromList cs)
fromList ('%' :: 's' :: cs) = FString (fromList cs)
fromList (c :: cs) = FChar c (fromList cs)
PrintfType : Format -> Type
PrintfType End = String
PrintfType (FInt rest) = Int -> PrintfType rest
PrintfType (FString rest) = String -> PrintfType rest
PrintfType (FChar c rest) = PrintfType rest
printf : (fmt: String) -> PrintfType (fromList $ unpack fmt)
printf fmt = printFormat (fromList $ unpack fmt) where
printFormat : (fmt: Format) -> PrintfType fmt
printFormat fmt = rec fmt "" where
rec : (f: Format) -> String -> PrintfType f
rec End acc = acc
rec (FInt rest) acc = \i: Int => rec rest (acc ++ (show i))
rec (FString rest) acc = \s: String => rec rest (acc ++ s)
rec (FChar c rest) acc = rec rest (acc ++ (pack [c]))
Run Code Online (Sandbox Code Playgroud)
Format是表示格式字符串的递归数据类型.FInt是一个int占位符,FString是一个字符串占位符,FChar是一个char文字.使用Format我可以定义PrintfType和实现printFormat.从那里,我可以顺利地扩展到一个字符串而不是一个List Char或一个Format值.最终结果是:
*sprintf> printf "the %s is %d" "answer" 42
"the answer is 42" : String
Run Code Online (Sandbox Code Playgroud)