2015-08-19 3 views
1

Я пишу менеджер пакетов, и я застрял в проверке, что файл установлен.Не удалось совместить тип `[Char] 'с` Value'

[1 of 1] Compiling Main    (../src/beaver.hs, ../src/.o/Main.o) 
../src/beaver.hs:57:37: 
Couldn't match type `[Char]' with `Value' 
Expected type: [Value] 
    Actual type: [[Char]] 
In the second argument of `mapM', namely `(splitOn " " files)' 
In a stmt of a 'do' block: mapM isFileInstalled (splitOn " " files) 

Вот код проблемной функции (ы):

installpkg = do 
      args <- getArgs 
      pkgname <- readProcess "beaver-pkgname" [(args !! 1)] "" 
      extractpkg pkgname 
      files <- metaprop "files" pkgname 
      mapM isFileInstalled (splitOn " " files) 
isFileInstalled f = do 
      dbcon <- openConnection "/var/lib/beaver/pkgs.db" 
      res <- execParamStatement dbcon "SELECT owner FROM files WHERE path = :path" [(":path", f)] :: IO (Either String [[Row Value]]) 
      when (null res) (putStrLn "file exists") 
      closeConnection dbcon 

я искал для решения, но я ничего не могу найти.

Также есть способ преобразования строки или текста в FilePath?

+0

См. Http://stackoverflow.com/help/mcve – Jubobs

ответ

3

Тип execParamStatement в isFileInstalled является:

execParamStatement :: SQLiteResult a => SQLiteHandle -> String -> [(String, Value)] -> IO (Either String [[Row a]]) 

, что означает, что [(":path", f)] имеет тип [(String, Value)] и f является dedecued, чтобы иметь тип Value.

Это все означает, что в качестве первого аргумента выводится isFileInstalled, чтобы принять Value.

Теперь в другой installpkg функции вы звоните:

mapM isFileInstalled (splitOn " " files) 

и mapM выводится как из:

mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b) 

к:

mapM :: (Value -> IO b) -> [Value] -> IO [b] 

для любой b выводится там (трудно понять, потому что вы не pu t явных сигнатур типа для функций).

Это означает, что ожидается, что mapM получит список [Value] от (splitOn " " files), что не так. (splitOn " " files) возвращает [String], что несовместимо с [Value].

Поскольку Value имеет конструктор, который принимает String, вы можете использовать:

(map Text . splitOn " " $ files) 

вместо:

(splitOn " " files) 

и сделать его типа проверить по крайней мере.


Кроме того, есть ли способ, чтобы преобразовать строку или текст FilePath?

Насколько FilePath обеспокоен, что это just an alias для String, так что вам не нужно преобразовать к нему, чтобы использовать его в контексте, где это требовалось String.


Наконец для тех, кто читает код и вы рассуждаете об этом, писать верхние типы уровней подписей для функций, спасибо.

+0

, если вы в зависимости от [system-filepath] (http://hackage.haskell.org/package/system-filepath-0.4.13.4) библиотеки FilePath ** не ** то же, что и 'String', хотя эта библиотека устарела, и несколько проектов все еще используют ее. – epsilonhalbe