![](/img/trans.png)
[英]understanding a Haskell function with filter and lambda expressions
[英]Understanding Haskell lambda expressions with lifting
我試圖理解清單 1中的代碼,它提升了基本數值運算以生成時變數字。 然后使用時變數來計算不同時間點之間的距離。 移動距離的計算“似乎”需要對一個Time
參數應用幾個 lambda 函數。 我不確定允許將一個參數應用於距離計算的確切評估機制:
(dist mp1 mp2) 2.0
( 1 )
我對 lambda 表達式和提升有一個基本的了解,但是我不明白他們在這段代碼中的組合。 任何對 ( 1 ) 的詳細評估的見解將不勝感激。
清單 1
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
module MovingPoint where
data Point a = Point { x ::a, y :: a } deriving Show
type Time = Double
type Moving v = Time -> v
-- Lifting functions
lift1 op a = \t -> op (a t)
lift2 op a b = \t -> op (a t) (b t)
class Number a where
add, sub, mul :: a -> a -> a
sqr, sqrt1 :: a -> a
sqr a = a `mul` a -- default def
-- define Number operations using builtin Num class
instance Number Double where
add = (+)
sub = (-)
mul = (*)
sqrt1 = sqrt
-- The calculation of the distance between two points
dist :: Number a => Point a -> Point a -> a
dist a b = sqrt1 (sqr((x a) `sub` (x b)) `add` sqr ((y a) `sub` (y b)))
-- Lift numbers. LHS ops are for (Moving Double), RHS ops are for Double
instance Number (Moving Double) where
add = lift2 add
sub = lift2 sub
mul = lift2 mul
sqrt1 = lift1 sqrt1
sqr = lift1 sqr
mp1, mp2 :: Point (Moving Double)
mp1 = Point (\t -> (4.0 `add` (0.5 `mul` t))) (\t -> (4.0 `sub` (0.5 `mul` t)))
mp2 = Point (\t -> (0.0 `add` (1.0 `mul` t))) (\t -> (0.0 `sub` (1.0 `mul` t)))
-- distance between mp1 and mp2 at times 2.0 and 10.0
md1 = (dist mp1 mp2) 2.0 -- > 5.8
md2 = (dist mp1 mp2) 10.0 -- > 9.05
評論答案
我無法正確格式化評論,所以我在這里添加了它。 專注於sqr
中的sub
,
sqrt1 (sqr((\t -> (4.0 + 0.5 * t)) sub (\t -> (0.0 + 1.0 * t)))...)
= 這個sub
的 arguments 都是(Moving Double)
,所以使用中綴表示法使用 def (lift2 (op) ab = \t -> (at) op (bt))
。
sqrt1 (sqr(\t -> (4.0 + 0.5 * t) - (0.0 + 1.0 * t))...)
我不確定這兩個\t
是如何變成一個\t
的。 顯然我錯過了一些東西。
要評估(dist mp1 mp2) 2.0
,讓我們從 function、 dist mp1 mp2
開始:
dist mp1 mp2
= -- def dist
sqrt1 (sqr((x mp1) `sub` (x mp2)) `add` sqr ((y mp1) `sub` (y mp2)))
= -- replace the cooridanates of the two points
sqrt1 (sqr((\t -> (4.0 `add` (0.5 `mul` t)))
`sub`
(\t -> (0.0 `add` (1.0 `mul` t))))
`add` ...) -- omitting the similar part
= -- the inner `add`, `mul` are the Double ones
sqrt1 (sqr((\t -> (4.0 + 0.5 * t)))
`sub`
(\t -> (0.0 + 1.0 * t))))
`add` ...)
= -- `sub` instead is the lifted subtraction since it's applied to `Moving Double`s
sqrt1 (sqr(\t -> (4.0 + 0.5 * t) - (0.0 + 1.0 * t))
`add` ...)
= -- `sqr` is lifted for the same reason
sqrt1 ((\t -> sqr((4.0 + 0.5 * t) - (0.0 + 1.0 * t)))
`add` ...)
= -- `add` is lifted, let the ... above be (\t -> ...2)
sqrt1 (\t -> sqr((4.0 + 0.5 * t) - (0.0 + 1.0 * t)) + ...2)
= -- `sqrt1` is lifted
\t -> sqrt (sqr((4.0 + 0.5 * t) - (0.0 + 1.0 * t)) + ...2)
最后,我們可以根據需要將最后一個 lambda 應用到2.0
,得到Double
結果。
請注意,要理解上述計算,重要的是要記住哪些表達式的計算結果為Double
s,哪些表達式的計算結果為Moving Double
s,以便我們可以根據需要進行提升。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.