最近我正在阅读一些涉及Haskell的函数式编程书籍.
看来Haskell非常喜欢"模块化程序",例如,
f :: (Integer,Integer) -> Integer
f = sum . map sq . filter . odd . between
Run Code Online (Sandbox Code Playgroud)
即使可以写出相同的功能
f' (m, n) = go m
where go m | m > n = 0
| otherwise = go (m + 1) + if odd m then sq m else 0
Run Code Online (Sandbox Code Playgroud)
"融合法"也很受欢迎并被使用(http://www.cs.ox.ac.uk/ralf.hinze/publications/IFL10.pdf)
我不是OCaml专家,但我会使用fold_left或fold_right尽可能简单高效(例如,无论如何我必须扫描整个列表并且不会停在中间).
但是,在大多数情况下,我将使用"模式匹配"编写显式递归代码.
另外我在github中读了很多OCaml项目,显式递归似乎很常见.
另外,我从未听说过OCaml的融合法.
我的问题是
当具有以下签名的函数有用时,任何人都可以分享良好的现实生活情况吗?
f (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)
我无法真正看到我需要的东西,比如来自Learn-you-a-haskell的教科书示例 [(+),(*)] <*> [1,2] <*> [3,4]
我发现了这些类型的签名:
x :: a b -> Int
x f = 3
y :: a b c -> Int
y f = 3
z :: a b c d -> Int
z f = 3
> x [1] -- 3
> y (1, 2) -- 3
> z (1, 2, 3) -- 3
Run Code Online (Sandbox Code Playgroud)
基本上:
它们是有效的,但我不确定它们的含义以及它们可以用于什么.
它们似乎与类型构造函数上的多类型概念或多态相关,但是基于类型构造函数接受的许多参数强制执行不变量.
我正在尝试这个(用于学习目的):
{-# LANGUAGE FlexibleInstances #-}
instance Monoid (a -> a) where
mempty = id
mappend f g = f . g
Run Code Online (Sandbox Code Playgroud)
期望id <> id等于id . id
但是,(id <> id) 1我收到此错误:
Non type-variable argument in the constraint: Monoid (a -> a)
Run Code Online (Sandbox Code Playgroud)
我应该改变什么来运行它?
这只是为了更好地理解monoids和Haskell类型类,而不是用于任何实际用途.
我正在为一种小型编程语言编写一个解释器,AST 看起来像这样:
\ndata Value a = IntVal a Int | FloatVal a Float\ndata Expr a = AddExpr a (Value a) (Value a) | MulExpr a (Value a) (Value a)\nRun Code Online (Sandbox Code Playgroud)\n我使用参数a来存储每个术语的行号。有些函数采用带注释的术语,有些函数采用空术语(用 替换a)unit,如下所示:
myFunction :: Value Int -> ...\nmyFunction = ...\n\nmyOtherFunction :: Value () -> ...\nmyOtherFunction = ...\nRun Code Online (Sandbox Code Playgroud)\n然而,我发现这个替代方案更清晰一些:
\ntype Annotated b = b Int\ntype Bare b = b ()\nRun Code Online (Sandbox Code Playgroud)\n然后,我可以像这样重写前两个函数:
\nmyFunction :: Annotated Value -> ...\nmyFunction = ...\n\nmyOtherFunction …Run Code Online (Sandbox Code Playgroud) 浮动文字必须包含小数点前后的数字;这可确保小数点不会被误认为是点字符的其他用途。
这可能还有什么用处?我无法想象任何这样的合法表达。
(为了澄清动机:我知道很多人都喜欢9.0或0.7一直在不需要的情况下写数字,但我不能完全与自己交朋友。我可以0.7选择更紧凑但其他更好的.7,但是重写的尾随零对我来说是错误的,除非它们表达的某个数量精确到十分之一,这在 Haskell 让我写9.0数字的场合很少见。)
replicate 3 . pred$8? ((replicate 3) . pred) 8但是replicate 3.pred$8?(replicate 3.0 pred)8.
有没有其中一个整数文字表达需要直接旁边站立.,没有空白?
我最近一直在玩MySQL-Simple.试图为该库提供一些全面的例子.我想将ID与我想要存储的实际记录分开.要为此Entity数据类型实现QueryResults的错误情况,我需要此数据类型实际使用的字段数量.因此我介绍了一个Arity类型类(很容易出错,特别是在数据发生变化时).我也在undefined这里用来调用方法的正确实例arity.
我在几个例子中看过这样的东西,但我对undefined这里的使用感到不安.有没有更好的方法来做到这一点?
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE BangPatterns #-}
module Main where
import Database.MySQL.Simple
import Database.MySQL.Simple.QueryResults
import Database.MySQL.Simple.QueryParams
import Database.MySQL.Simple.Result
import Database.MySQL.Simple.Param
connectInfo :: ConnectInfo
connectInfo = defaultConnectInfo { connectUser = "dbuser" }
data Person = Person { personName :: String
, personAge :: Int
} deriving Show
class Arity a where
arity :: a -> Int
instance Arity Person where
arity _ = 2
instance QueryResults Person where
convertResults [fname, …Run Code Online (Sandbox Code Playgroud) 如前面的问题所述,您可以将提交拆分为较小的补丁.但是,这些答案建议git add -p,这可以完成工作,但如果我想要的是每个块的一次提交,则按照文件中的给定顺序进行繁琐.有没有办法实现这一点,自动?
在这里,我又回来了(对我而言)我最新杰作的奇怪行为......
此代码应该读取文件,但它不会:
readCsvContents :: String -> IO ( String )
readCsvContents fileName = do
withFile fileName ReadMode (\handle -> do
contents <- hGetContents handle
return contents
)
main = do
contents <- readCsvContents "src\\EURUSD60.csv"
putStrLn ("Read " ++ show (length contents) ++ " Bytes input data.")
Run Code Online (Sandbox Code Playgroud)
结果是
Read 0 Bytes input data.
Run Code Online (Sandbox Code Playgroud)
现在我改变了第一个函数并添加了一个putStrLn:
readCsvContents :: String -> IO ( String )
readCsvContents fileName = do
withFile fileName ReadMode (\handle -> do
contents <- hGetContents handle
putStrLn ("hGetContents gave …Run Code Online (Sandbox Code Playgroud) 我不确定我在这里做错了什么:
data Vector2D u = Vector2D {
_x :: u,
_y :: u
} deriving stock (Show, Eq, Functor, Foldable, Traversable)
{-# INLINE addVector2 #-}
addVector2 :: (Additive a) => Vector2D a -> Vector2D a -> Vector2D a
addVector2 (Vector2D { _x = x1, _y = y1 }) (Vector2D { _x = x2, _y = y2 }) =
Vector2D { _x = x1 + x2, _y = y1 + y2 }
instance (Additive a) => Additive (Vector2D a) where
(+) …Run Code Online (Sandbox Code Playgroud)