在WriterT中包装可能以添加日志记录

时间:2016-03-27 11:28:16

标签: haskell monad-transformers maybe writer-monad

我完全陷入了困境,我觉得我现在可以使用一些帮助,只是为了保持理智。我想要一些简单的事情,就像为返回Maybe的函数添加日志记录功能一样简单,但无论我怎么努力,我都无法获得正确的类型。

这是(我认为)最接近的:

import Data.Maybe
import Control.Monad
import Control.Monad.Writer

q :: Integer -> Maybe Integer
q x = if x > 7
      then Just x
      else Nothing

qlog :: Integer -> WriterT [String] Maybe Integer
qlog x = do
  tell ["Querying " ++ show x]
  return $ q x

这仍然让我输入错误:

Couldn't match type ‘Maybe Integer’ with ‘Integer’
Expected type: WriterT [String] Maybe Integer
  Actual type: WriterT [String] Maybe (Maybe Integer)
In a stmt of a 'do' block: return $ q x
In the expression:
  do { tell ["Querying " ++ show x];
       return $ q x }
In an equation for ‘qlog’:
    qlog x
      = do { tell ["Querying " ++ show x];
             return $ q x }

我应该如何调整代码以使其编译和工作?

非常感谢你的帮助,Haskellers同事!

1 个答案:

答案 0 :(得分:3)

为了进行类型检查,内部monad应为lifted

Public Sub FormulaGenerator()
    Dim ws As Worksheet
    Dim firstRow As Long
    Dim lastRow As Long
    Dim dateRange As Range
    Dim cell As Range
    Dim hitList As Collection
    Dim refMonth As Integer
    Dim thisMonth As Integer
    Dim r As Long
    Dim output() As Variant
    Dim item As Variant

    'Set these for your own task.
    Set ws = ThisWorkbook.Worksheets("Sheet1")
    firstRow = 3
    lastRow = 20

    'Read the values cell by cell
    Set dateRange = ws.Range(ws.Cells(firstRow, "A"), ws.Cells(lastRow, "A"))
    Set hitList = New Collection
    For Each cell In dateRange.Cells
        item = cell.Month
        thisMonth = Month(cell.Value)
        If thisMonth <> refMonth Then
            'It's a new month so populate the collection with the cell address
            hitList.Add cell.Address(False, False)
            refMonth = thisMonth
        End If
    Next

    'Populate the output array values
    ReDim output(1 To hitList.Count, 1 To 1)
    r = 1
    For Each item In hitList
        output(r, 1) = "=MONTH(" & item & ")"
        r = r + 1
    Next

    'Write the output array starting at cell "F2"
    ws.Cells(2, "F").Resize(UBound(output, 1)).Formula = output
End Sub

因此,您需要写Public Sub OutputGenerator() Dim ws As Worksheet Dim firstRow As Long Dim lastRow As Long Dim dates As Variant Dim hitList As Collection Dim refMonth As Integer Dim thisMonth As Integer Dim r As Long Dim output() As Integer Dim item As Variant 'Set these for your own task. Set ws = ThisWorkbook.Worksheets("Sheet1") firstRow = 3 lastRow = 23 'Read the dates into an array dates = ws.Range(ws.Cells(firstRow, "A"), ws.Cells(lastRow, "A")).Value 'Loop through the array to acquire each new date Set hitList = New Collection For r = 1 To UBound(dates, 1) thisMonth = Month(dates(r, 1)) If thisMonth <> refMonth Then 'It's a new date so populate the collection with the month integer hitList.Add thisMonth refMonth = thisMonth End If Next 'Populate the output array ReDim output(1 To hitList.Count, 1 To 1) r = 1 For Each item In hitList output(r, 1) = item r = r + 1 Next 'Write the output array starting at cell "F2" ws.Cells(2, "F").Resize(UBound(output, 1)).Value = output End Sub 而不是lift :: (Monad m, MonadTrans t) => m a -> t m a ; return $ q x;如:

lift $ q x