Переписывание функций haskell без вызова IO - PullRequest
0 голосов
/ 27 сентября 2019

Прежде всего, я относительно новичок в программировании и, в частности, в 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 и рекурсивный вызов одновременно.Есть указатели?

...