fromPathPiece有type()

时间:2014-12-19 15:42:06

标签: haskell yesod

我在我的网页上一次使用多个表单,当用户点击“更新”时,我需要确定哪条记录与返回的表单数据一致。

现在我正在尝试使用toPathPiece / fromPathPiece执行此操作,并将密钥存储在表单上的隐藏文本字段中。

文本返回正常,所以我得到了类似“3”的内容。但是当我尝试使用密钥进行替换时出现此错误:

Handler/Song.hs:137:15:
    Couldn't match type ‘()’ with ‘Key SongChord’
    Expected type: HandlerT App IO (Key SongChord)
      Actual type: HandlerT App IO ()
    In a stmt of a 'do' block: runDB $ replace sc_id sc
    In the expression: do { runDB $ replace sc_id sc }
    In a case alternative:
        Just sc_id -> do { runDB $ replace sc_id sc }

以下是有问题的代码:

(_, _, Just _) -> do
  chordz <- runDB $ selectList [SongChordSong ==. sid] [Asc SongChordSeqnum]
  chordroots <- runDB $ selectList [] []
  notesets <- runDB $ selectList [] [] 
  let rootz = map (\(Entity crid cr) -> (chordRootName cr, crid)) chordroots
      nsetz = map (\(Entity nsid ns) -> (noteSetName ns, nsid)) notesets 
  ((res, widget),enctype) <- 
    runFormPost $ scfForm Nothing sid (length chordz) rootz nsetz 
  case res of 
    FormSuccess scf -> do
      -- fromScf takes the form datatype and returns (Text,SongChord)
      let (mbsctext, sc) = fromScf scf
          mbscid = fromPathPiece mbsctext :: Maybe (Key SongChord)
      sck <- case mbscid of 
        Nothing -> do 
          runDB $ insert sc
        Just sc_id -> do
          -- runDB $ insert sc
          -- here's the problem!
          runDB $ replace sc_id sc 
      defaultLayout $ [whamlet|
        <h1> #{show mbscid}
        <br> #{show sck}
        <br> #{show scf}
        |]

如果我注释掉替换(并取消注释插入)然后它编译并运行,结果网页上有mbscid,看起来它是一个有效的密钥。在这种情况下,这是页面中的文本:

Just (SongChordKey {unSongChordKey = SqlBackendKey {unSqlBackendKey = 2}})

SongChordKey {unSongChordKey = SqlBackendKey {unSqlBackendKey = 16}}

Scf {song = SongKey {unSongKey = SqlBackendKey {unSqlBackendKey = 1}}, chordroot = ChordRootKey {unChordRootKey = SqlBackendKey {unSqlBackendKey = 9}}, noteset = NoteSetKey {unNoteSetKey = SqlBackendKey {unSqlBackendKey = 2}}, seqnum = 15, duration = 202, scid = "2"}
Insert copyright statement here

1 个答案:

答案 0 :(得分:4)

查看insertreplace的类型(忽略简洁约束):

insert :: val -> m (Key val)
replace :: Key val -> val -> m ()

case表达式的分支必须具有相同的类型。 (否则sck的类型将根据所采用的分支而有所不同。)因为insertreplace调用是其各自分支中的最后一个表达式,所以它们的类型必须匹配。由于其类型中的Key val()不同,因此您会收到该错误。

您可以通过返回密钥来使replace分支具有正确的类型:

Just sc_id -> do
    runDB $ replace sc_id sc
    return sc_id