如何将函数定义拉入类型类,而不是引用

  • 本文关键字:引用 类型 函数 定义 haskell
  • 更新时间 :
  • 英文 :


我在下面提供了一些代码来演示项目的基本概念。我有模块被设置为接口;我实现了构建模块的接口。在下面的例子中,我构建了一个Alpha.

type Ticker = String
type Shares = Int
type Price = Float
data Insight = Down | Flat | Up deriving (Show, Eq, Ord)
type Target = Float
data Universe = Universe {generateUniverse :: [(Ticker, Price)] -> [(Ticker, Price)]}
data Alpha = Alpha {generateInsights :: [(Ticker, Price)] -> [(Ticker, Insight)]}
data Portfolio = Portfolio {generateTargets :: [(Ticker, Insight)] -> [(Ticker, Target)]}
data Execution = Execution {generateOrders :: [(Ticker, Price)] -> [(Ticker, Target)] -> [(Ticker, Shares)]}
convert :: (Ticker, Price) -> (Ticker, Insight)
convert (t, p)
| p < 500 = (t, Down)
| p == 500 = (t, Flat)
| p > 500 = (t, Up)
split :: [(Ticker, Price)] -> [(Ticker, Insight)]
split xs = foldr (tp acc -> (convert tp):acc) [] xs
splitAlpha :: Alpha
splitAlpha = Alpha {
generateInsights = split
}
main :: IO ()
main = do
let
alpha = splitAlpha
print (generateInsights alpha [("TSLA", 500.0), ("RKT", 10.0), ("AMC", 750)])

我如何压缩splitAlpha的定义,使generateInsights的定义中没有那么多嵌套?我已经尝试了下面的例子…

convert :: (Ticker, Price) -> (Ticker, Insight)
convert (t, p)
| p < 500 = (t, Down)
| p == 500 = (t, Flat)
| p > 500 = (t, Up)
splitAlpha :: Alpha
splitAlpha = Alpha {
generateInsights xs = foldr (tp acc -> (convert tp):acc) [] xs
}

并收到此错误:

ghci> :cmd return $ unlines [":l itk", ":main"]
[1 of 1] Compiling Main             ( itk.hs, interpreted )
itk.hs:23:20: error: parse error on input `xs'
|
23 |   generateInsights xs = foldr (tp acc -> (convert tp):acc) [] xs
|                    ^^
Failed, no modules loaded.
<interactive>:60:53: error:
* Variable not in scope: main :: IO a0
* Perhaps you meant `min' (imported from Prelude)

您可以使用lambda表达式,因此:

splitAlpha :: Alpha
splitAlpha = Alpha {
generateInsights =xs ->foldr (tp acc -> (convert tp):acc) [] xs
}

在这个特定的例子中,这只是一个映射函数,所以你可以使用:

splitAlpha :: Alpha
splitAlpha = Alpha {
generateInsights =map convert
}

正如Willem Van Onsem所写,这个例子非常简单,因为整个事情归结为generateInsights = map convert。但一般来说,这并不容易。Lambda语法只适用于没有保护的单子句函数

splitAlpha = Alpha
{ generateInsights = xs -> ...
}

更一般地说,您总是可以使用let来拥有一个适当的定义作用域,在这个作用域中,您可以用完整的语法在本地定义任何函数,但避免填充任何其他名称空间:

splitAlpha = Alpha
{ generateInsights
= let gi xs = foldr (tp acc -> (convert tp):acc) [] xs
in gi
}

最新更新