Haskell 中 LinkedList Monad 的验证

Verification of LinkedList Monad in Haskell

我还在学习 Haskell,目前我正在练习 monad。现在,我在 Haskell 中定义了一个 LinkedList monad 并实现了它,但我不完全确定我是否在正确的轨道上。我不确定的原因是我没有在其他函数(例如 add 或 getFirstItem)中使用 bind 或 unit 函数。

到目前为止,这是我的代码:

module LinkedList where

import Control.Applicative
import Control.Monad (ap)

data LinkedList a = Success (a, LinkedList a) | Null | Fail String

instance (Show a) => Show (LinkedList a) where
    show (Success (x, previous)) = (show x) ++ " ~ " ++ (show previous)
    show (Fail s) = "An error occured " ++ s
    show Null = "END"

instance Functor LinkedList where
    fmap f (Success (x, y)) = Success (f x, fmap f y)
    fmap f Null = Null
    fmap f (Fail s) = Fail s

instance Applicative LinkedList where
    pure  = return
    (<*>) = ap

instance Monad LinkedList where
    return x = Success (x, Null)
    (Success (x, xs)) >>= f = Success (getFirstItem (f x), xs >>= f)
    (Fail s) >>= f = Fail s
    Null >>= f = Null

-- Get the first element from the LinkedList
getFirstItem :: LinkedList a -> a
getFirstItem (Success (x, xs)) = x
getFirstItem Null = error "Cannot take first element of empty list"
getFirstItem (Fail s) = error (show s)

-- Get the nth element from the LinkedList
getItem :: LinkedList a -> Integer -> a
getItem (Success (x, xs)) n = if n == 0 then x else getItem xs (n - 1)
getItem (Fail s) _ = error (show s)
getItem Null _ = error "LinkedList out of bounds"

-- Add a single element to the LinkedList
add :: LinkedList a -> a -> LinkedList a
add (Success (x, xs)) y = Success (x, (add xs y))
add Null y = Success (y, Null)
add (Fail s) _ = error (show s)

你必须验证 monad 法则,看看你是否在正确的轨道上。先说左恒等式:

return a >>= f = f a

让我们将f函数设为:

testFun :: Int -> LinkedList Int
testFun x = Success (x + 2, Fail "hello")

让我们计算 return 3 >>= testFun:

return 3 = Success (3, Null)
return 3 >>= testFun = Success (5, Null)

让我们计算 testFun 3:

testFun 3 = Success (5, Fail "hello")

Success (5, Null) 不等于 Success (5, Fail "hello").

所以它不是一个合适的 monad。