Tôi đang cố gắng triển khai turtle graphics trong Haskell. Mục đích là để có thể viết một hàm như thế này:Đồ họa Rùa là một Haskell Monad
draw_something = do
forward 100
right 90
forward 100
...
và sau đó có nó tạo ra một danh sách các điểm (có thể với những đặc tính bổ sung):
> draw_something (0,0) 0 -- start at (0,0) facing east (0 degrees)
[(0,0), (0,100), (-100,100), ...]
Tôi có tất cả làm việc này trong một 'bình thường', nhưng tôi đã thất bại trong việc thực hiện nó như một Haskell Monad và sử dụng ký hiệu. Các mã cơ bản:
data State a = State (a, a) a -- (x,y), angle
deriving (Show, Eq)
initstate :: State Float
initstate = State (0.0,0.0) 0.0
-- constrain angles to 0 to 2*pi
fmod :: Float -> Float
fmod a
| a >= 2*pi = fmod (a-2*pi)
| a < 0 = fmod (a+2*pi)
| otherwise = a
forward :: Float -> State Float -> [State Float]
forward d (State (x,y) angle) = [State (x + d * (sin angle), y + d * (cos angle)) angle]
right :: Float -> State Float -> [State Float]
right d (State pos angle) = [State pos (fmod (angle+d))]
bind :: [State a] -> (State a -> [State a]) -> [State a]
bind xs f = xs ++ (f (head $ reverse xs))
ret :: State a -> [State a]
ret x = [x]
Với điều này bây giờ tôi có thể viết
> [initstate] `bind` (forward 100) `bind` (right (pi/2)) `bind` (forward 100)
[State (0.0,0.0) 0.0,State (0.0,100.0) 0.0,State (0.0,100.0) 1.5707964,State (100.0,99.99999) 1.5707964]
Và có được kết quả mong đợi. Tuy nhiên tôi không thể thực hiện trường hợp này là Monad
.
instance Monad [State] where
...
kết quả trong
`State' is not applied to enough type arguments
Expected kind `*', but `State' has kind `* -> *'
In the instance declaration for `Monad [State]'
Và nếu tôi quấn danh sách trong một đối tượng mới
data StateList a = StateList [State a]
instance Monad StateList where
return x = StateList [x]
tôi nhận được
Couldn't match type `a' with `State a'
`a' is a rigid type variable bound by
the type signature for return :: a -> StateList a
at logo.hs:38:9
In the expression: x
In the first argument of `StateList', namely `[x]'
In the expression: StateList [x]
tôi đã cố gắng phiên bản khác nhau nhưng tôi không bao giờ làm cho nó chạy như tôi muốn. Tôi đang làm gì sai? Tôi hiểu gì không chính xác?
Nên có thể triển khai thực đơn rùa, phát triển lịch sử vị trí và tiêu đề rùa. Nhưng cách bạn đang cố gắng triển khai thực thể 'Monad' gây nhầm lẫn kiểu được sử dụng để biểu diễn các số trong lịch sử này với các kiểu giá trị nói chung. Các tính toán liên quan đến 'ret' và' bind' của bạn chỉ xem xét các giá trị. Nhưng 'return' và' >> = 'nên giải thích cách tổ chức tính toán liên quan đến giá trị của bất kỳ loại nào, một số trong đó cũng có thể mở rộng đường mòn của con rùa. – pigworker
Nếu bạn muốn "đơn nguyên" tạo danh sách các điểm thì bạn có thể muốn Writer + State thay vì State. Writer thường là "đơn thuần tích lũy" mặc dù nó có thể hoạt động theo những cách khác. Để tiến bộ bạn cũng cần phải xem xét lý do tại sao các monads trạng thái là các hàm được bao bọc bởi một 'newtype' - chúng là các hàm từ trạng thái hiện tại đến một cặp trạng thái mới cộng với câu trả lời, không chỉ trạng thái mới. Thường thì câu trả lời là 'unit' aka(). ví dụ: về phía trước thường sẽ là 'forward :: Float -> Turtle()' giả định một đơn nguyên được gọi là Rùa. –