Прежде всего, я относительно новичок в программировании и, в частности, в Haskell, так что а) извиняюсь за возможный базовый вопрос и б) если какие-либо будущие ответы можно будет сделать таким же базовым образом, это будет более чем оценено!
Полный контекст: я собираюсь вызвать утку функцию отладки из Python с использованием шаблона, изложенного в Pyduckling для использования Haskell'sинтерфейс внешней функции.Проблема заключается в том, что функция parse
, которую реализует Pyduckling, имеет тип возврата [Entity]
, тогда как функция debug
выводит IO [Entity]
.Когда я пытался реплицировать функцию Pyduckling hs_parse
для отладки
hs_debug :: CString -> CString -> CLong -> IO CString
hs_debug text lang time = do
hs_text <- peekCString text
hs_lang <- peekCString lang
utcNow <- getCurrentTime
case hs_text of
[] -> do
newCString "No string to parse"
_ -> do
refTime <- return $ _makeReftime (TimeZoneSeries utc []) (millisToUTC $ fromIntegral time)
let
context = Context
{ referenceTime = refTime
, lang = parseLang hs_lang
}
options = Options
{ withLatent = False
}
parsedEntites = debugCustom context (Text.pack hs_text) options [This Time]
newCString $ Text.unpack $ toJText parsedEntites
, в сообщении об ошибке сообщалось, что в newCString $ Text.unpack $ toJText parsedEntities
не существует экземпляра для Data.Aeson.Types.ToJSON.ToJSON (IO [Entity])
, возникающего в результате использования toJText.
Функция для toJText
выглядит следующим образом:
toJText = Text.decodeUtf8 . LB.toStrict . encode
Одним из решений может быть переписать hs-debug
для вывода IO ()
, но я бы не знал, как это повлияет на FFI,которая в настоящее время является самой загадочной частью процесса, и которую я хочу сохранить ближе к действующему примеру.
Итак, исправление, которое я выбрал, - это удаление ввода-вывода из функции debug
.В конечном итоге это сводится к следующим связанным функциям:
ptree :: Text -> Entity -> IO ()
ptree sentence Entity {enode} = pnode sentence 0 enode
pnode :: Text -> Int -> Node -> IO ()
pnode sentence depth Node {children, rule, nodeRange = Range start end} = do
Text.putStrLn out
mapM_ (pnode sentence (depth + 1)) children
where
out = Text.concat [ Text.replicate depth "-- ", name, " (", body, ")" ]
name = fromMaybe "regex" rule
body = Text.drop start $ Text.take end sentence
Я искал, возможно ли связать последовательность вычислений вне do
безрезультатно, так как кажется, что все, что нужносделано, чтобы вычислить out
для каждого узла дерева.Я не знаю, как может выглядеть рекурсия в этом случае, так как я не знаю, как связать воедино вычисления для out
и рекурсивный вызов одновременно.Есть указатели?