foldM 与 monad 状态不进行类型检查

问题描述 投票:0回答:1
  • 关于
    foldM
    的现有问题(例如 herehere)并未解决
    State
    monad。
  • 文档没有指定示例,我什至无法编译一个简单的示例。
import Control.Monad.State.Lazy
import Control.Monad ( foldM )

data Student = Student { name :: String, sid :: Int } deriving ( Show )
data TestResult = TestResult { tested :: Student, grade :: Int } deriving ( Show )
data Classroom = Classroom { students :: [ Student ] } deriving ( Show )

test :: Student -> State Classroom TestResult
test s = do { c <- get; put c { students = s:(students c) }; return $ TestResult { tested = s, grade = 2 * (sid s) } }

tests :: [ Student ] -> State Classroom [ TestResult ]
tests = mapM test

worst :: State Classroom TestResult
worst = return $ TestResult { tested = Student { name = "MMM", sid = 0 }, grade = 0 }

better :: TestResult -> TestResult -> State Classroom TestResult
better r1 r2 = return $ case (grade r1) < (grade r2) of { True -> r2; False -> r1 }

brightest :: [ Student ] -> State Classroom TestResult
brightest students = foldM better worst (tests students)

main = print $ evalState (brightest [ Student "X" 19, Student "Y" 49, Student "Z" 46 ]) (Classroom [])

这是我得到的错误 - 我错过了什么?

Main.hs:22:35: error: [GHC-83865]
    • Couldn't match type ‘StateT
                             Classroom Data.Functor.Identity.Identity TestResult’
                     with ‘TestResult’
      Expected: TestResult
        Actual: State Classroom TestResult
    • In the second argument of ‘foldM’, namely ‘worst’
      In the expression: foldM better worst (tests students)
      In an equation for ‘brightest’:
          brightest students = foldM better worst (tests students)
   |
22 | brightest students = foldM better worst (tests students)
   |                                   ^^^^^

Main.hs:22:42: error: [GHC-83865]
    • Couldn't match type ‘[TestResult]’ with ‘TestResult’
      Expected: StateT
                  Classroom Data.Functor.Identity.Identity TestResult
        Actual: State Classroom [TestResult]
    • In the third argument of ‘foldM’, namely ‘(tests students)’
      In the expression: foldM better worst (tests students)
      In an equation for ‘brightest’:
          brightest students = foldM better worst (tests students)
   |
22 | brightest students = foldM better worst (tests students)
   |                                          ^^^^^^^^^^^^^^
haskell fold
1个回答
0
投票

foldM
函数仅期望第一个参数产生一个单子值。第二个和第三个参数应该是正常值。所以你需要做一些拆包:

worst :: TestResult
worst = TestResult { tested = Student { name = "MMM", sid = 0 }, grade = 0 }

brightest :: [ Student ] -> State Classroom TestResult
brightest students = do
  ts <- tests students
  foldM better worst ts
© www.soinside.com 2019 - 2024. All rights reserved.