cib*_*en1 1 polymorphism haskell interface
我再次请求关于如何在Haskell中实现给定设计的评论.在此先感谢所有提供有用评论的人.此外,我希望这可以帮助像我这样的其他Haskell新手,有一个实用的示例代码.
这一次,我们有一个多态函数doSampling(在模块Samples中),它接受泛型函数f和一个实数(索引)列表并返回一个Samples(索引,值= f(索引)).我们doSampling只需要实现一次,因为如果f是a Polynomial或a 则无关紧要Sinus.为此,我们引入了一个接口函数,并使用Polynomial和Sinus类型实现它.以下是正在实施的设计:

关于Function接口(Haskell中的类)存在争议.有人建议它实际上并不是必需的,因为doSampling可能会采用"裸体"功能(Double -> Double).但是,如何做到这一点,如果你需要的裸体函数内一些额外的状态多项式,功放+频率+相对于窦(coeffs?
kosmikus和Chris Taylor非常好的答案.谢谢.两者中的一个关键想法:有
doSampling :: (Double -> Double) -> [Double] -> Samples
这是:它需要一个函数(Double -> Double)(而不是Function)并列出并返回样本.
我的目的是保持Polynomials和Sinuses 的状态.在克里斯的答案中没有考虑到这一点,但它在kosmikus中.另一方面,Function如果您无法访问源代码,kosmikus版本中的弱点可能是如何扩展其定义.
我还要指出:
克里斯的想法是(Double -> Double)通过工厂函数将多项式或正弦曲线封装到函数中,mkPolynomial或者mkSinus生成(使用currying?)获取适当参数的所需函数.(虽然你以后不能参考参数).
kosmikous'使用value转换(也使用currying?)a 的想法Functiona(Double -> Double)
这两个答案都值得一读,因为他们有其他一些小的Haskell技巧来减少和简化代码.
克里斯的答案不支持保持多项式或窦的状态
kosmikus答案是不可扩展的:添加新类型的函数(Cosinus ......)
我的答案(冗长)确实克服了以前的缺点,它允许(这不是问题所必需的)强制函数类型除了value(在java-interfaces如何工作的意义上)之外还有更多的关联函数.
主要(用法)
import Polynomial
import Sinus
import Function
import Samples
-- ...............................................................
p1 = Polynomial [1, 0, 0.5] -- p(x) = 1 + 0.5x^2
s1 = Sinus 2 0.5 3 -- f(x) = 2 sin(0.5x + 3)
-- ...............................................................
-- sample p1 from 0 to 5
m1 = doSampling p1 [0, 0.5 .. 5]
m2 = doSampling s1 [0, 0.5 .. 5]
-- ...............................................................
-- main
-- ...............................................................
main = do
putStrLn "Hello"
print $ value p1 2
print $ value s1 (pi/2)
print $ pairs m1
print $ pairs m2
Run Code Online (Sandbox Code Playgroud)
功能
module Function where
-- ...............................................................
-- "class type" : the types belonging to this family of types
-- must implement the following functions:
-- + value : takes a function and a real and returns a real
-- ...............................................................
class Function f where
value :: f -> Double -> Double
-- f is a type variable, this is:
-- f is a type of the Function "family" not an actual function
Run Code Online (Sandbox Code Playgroud)
样品
module Samples where
import Function
-- ...............................................................
-- Samples: new data type
-- This is the constructor and says it requieres
-- two list, one for the indexes (xs values) and another
-- for the values ( ys = f (xs) )
-- this constructor should not be used, instead use
-- the "factory" function: new_Samples that performs some checks
-- ...............................................................
data Samples = Samples { indexes :: [Double] , values :: [Double] }
deriving (Show)
-- ...............................................................
-- constructor: it checks lists are equal size, and indexes are sorted
new_Samples :: [Double] -> [Double] -> Samples
new_Samples ind val
| (length ind) /= (length val) = samplesVoid
| not $ isSorted ind = samplesVoid
| otherwise = Samples ind val
-- ...............................................................
-- sample a funcion
-- it takes a funcion f and a list of indexes and returns
-- a Samples calculating the values array as f(indexes)
doSampling :: (Function f) => f -> [Double] -> Samples
doSampling f ind = new_Samples ind vals
where
vals = [ value f x | x <- ind ]
-- ...............................................................
-- used as "error" in the construction
samplesVoid = Samples [] []
-- ...............................................................
size :: Samples -> Int
size samples = length (indexes samples)
-- ...............................................................
-- utility function to get a pair (index,value) out of a Samples
pairs :: Samples -> [(Double, Double)]
pairs samples = pairs' (indexes samples) (values samples)
pairs' :: [Double] -> [Double] -> [(Double, Double)]
pairs' [] [] = []
pairs' [i] [v] = [(i,v)]
pairs' (i:is) (v:vs) = (i,v) : pairs' is vs
-- ...............................................................
-- to check whether a list is sorted (<)
isSorted :: (Ord t) => [t] -> Bool
isSorted [] = True
isSorted [e] = True
isSorted (e1:(e2:tail))
| e1 < e2 = isSorted (e2:tail)
| otherwise = False
Run Code Online (Sandbox Code Playgroud)
窦
module Sinus where
-- ...............................................................
import Function
-- ...............................................................
-- Sinus: new data type
-- This is the constructor and says it requieres
-- a three reals
-- ...............................................................
data Sinus = Sinus { amplitude :: Double, frequency :: Double, phase :: Double }
deriving (Show)
-- ...............................................................
-- we say that a Sinus is a Function (member of the class Function)
-- and then, how value is implemented
instance Function Sinus where
value s x = (amplitude s) * sin ( (frequency s)*x + (phase s))
Run Code Online (Sandbox Code Playgroud)
多项式
module Polynomial where
-- ...............................................................
import Function
-- ...............................................................
-- Polynomial: new data type
-- This is the constructor and says it requieres
-- a list of coefficients
-- ...............................................................
data Polynomial = Polynomial { coeffs :: [Double] }
deriving (Show)
-- ...............................................................
degree :: Polynomial -> Int
degree p = length (coeffs p) - 1
-- ...............................................................
-- we say that a Polynomial is a Function (member of the class Function)
-- and then, how value is implemented
instance Function Polynomial where
value p x = value' (coeffs p) x 1
-- list of coeffs -> x -> pw (power of x) -> Double
value' :: [Double] -> Double -> Double -> Double
value' (c:[]) _ pw = c * pw
value' (c:cs) x pw = (c * pw) + (value' cs x x*pw)
Run Code Online (Sandbox Code Playgroud)
Chr*_*lor 12
你当然不需要这Function门课.所有这些重量级的类,实例,成员变量fluff都是Haskell旨在避免的事情之一.纯函数可以更灵活.
这是一种做你想做的事情的简单方法.
type Sample = ([Double], [Double])
newSample xs vs
| isSorted xs && length xs == length vs = (indices, values)
| otherwise = ([], [])
pairs = uncurry zip
doSampling :: (Double -> Double) -> [Double] -> Sample
doSampling f xs = newSample xs (map f xs)
mkPolynomial :: [Double] -> (Double -> Double)
mkPolynomial coefs x = go coefs
where
go [] = 0
go (c:cs) = c + x * go cs
mkSinus :: Double -> Double -> Double -> (Double -> Double)
mkSinus amp freq phase x = amp * sin (freq * x + phase)
p1 = mkPolynomial [1, 0, 0.5] -- 1 + 0.5x^2
s1 = mkSinus 2 0.5 3 -- 2 sin(0.5x + 3)
m1 = doSampling p1 [0, 0.5 .. 5]
m2 = doSampling s1 [0, 0.5 .. 5]
main :: IO ()
main = do
print $ p1 2
print $ s1 (pi/2)
print $ pairs m1
print $ pairs m2
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
286 次 |
| 最近记录: |