我有一个关于日期和StringHaskell 的初学者问题.
我需要像String在Haskell中那样获得日期(年,月或日)的一部分.我发现,如果我在GHCi中写下以下两行
Prelude> now <- getCurrentTime
Prelude> let mon = formatTime defaultTimeLocale "%B" now
Run Code Online (Sandbox Code Playgroud)
那mon是类型String.但是,我无法将其置于一个功能中.我试过以下内容:
getCurrMonth = do
now <- getCurrentTime
putStrLn (formatTime defaultTimeLocale "%B" now)
Run Code Online (Sandbox Code Playgroud)
但这会返回类型IO (),我需要String(也不是IO String,只String).
我理解该do语句创建了一个我不想要的monad,但我一直无法找到任何其他解决方案来获取Haskell中的日期.
那么,有没有办法写这样的函数?
在此先感谢您的帮助!
我有一些GADT代表lambda演算中的一个术语.
data Term a =
Var a
| Lambda a (Term a)
| Apply (Term a) (Term a)
Run Code Online (Sandbox Code Playgroud)
我想要做的是在该类型上有一个通用的转换接口.它应该具有类似于此的类型签名:
(Term a -> Term a) -> Term a -> Term a
Run Code Online (Sandbox Code Playgroud)
编写此函数很容易:
fmap' :: (Term a ? Term a) ? Term a ? Term a
fmap' f (Var v) = f (Var v)
fmap' f (Lambda v t) = Lambda v (fmap' f t)
fmap' f (Apply t1 t2) = Apply (fmap' f t1) (fmap' f t2)
Run Code Online (Sandbox Code Playgroud)
所以,我的问题是haskell(或haskell库)中有某种通用结构来进行这种转换(类似于Functor它应该叫做态射)?
受比较列表长度的启发
如果我想在列表列表中找到最长的列表,最简单的方法可能是:
longestList :: [[a]] -> [a]
longestList = maximumBy (comparing length)
Run Code Online (Sandbox Code Playgroud)
一种更有效的方法是预先计算长度:
longest :: [[a]] -> [a]
longest xss = snd $ maximumBy (comparing fst) [(length xs, xs) | xs <- xss]
Run Code Online (Sandbox Code Playgroud)
现在,我想更进一步.对于正常情况,它可能没有效率,但你能用箭头解决这个问题吗?我的想法基本上是,同时逐步浏览所有列表,并继续踩到你超越每个列表的长度,除了最长的.
longest [[1],[1],[1..2^1000],[1],[1]]
Run Code Online (Sandbox Code Playgroud)
在前面(非常人为的)示例中,您只需要在每个列表中执行两个步骤,以确定列表[1..2^1000]是最长的,而无需确定所述列表的整个长度.我是对的,这可以用箭头完成吗?如果是这样,那怎么样?如果没有,那么为什么不,以及如何实施这种方法?
这是我得到的:
{-# LANGUAGE MultiParamTypeClasses
, FlexibleInstances #-}
class ListResultMult r a where
lstM :: a -> [a] -> r
listM :: ListResultMult r a => a -> r
listM a = lstM a []
instance ListResultMult r a => ListResultMult (a -> r) a where
lstM a as x = lstM x $ a:as
instance ListResultMult [a] a where
lstM a as = reverse $ a:as
Run Code Online (Sandbox Code Playgroud)
以下是它的工作原理:
> listM 'a' 'b' 'c' :: String
"abc"
> putStrLn $ listM 'a' …Run Code Online (Sandbox Code Playgroud) 我有时发现自己编写这样的代码:
someFunc :: Foo -> Int
someFunc foo = length $ do
x <- someList
guard someGuard
return ()
Run Code Online (Sandbox Code Playgroud)
或等效地:
someFunc foo = length [() | x <- someList, someGuard]
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来执行这种计算?更高效?更具可读性?更惯用吗?
假设我在抽象语法树数据类型上编写"替换"函数:
data Term = Id String
| If Term Term Term
| Let String Term Term
...
subst :: String -- name of identifier to replace
-> Term -- term to replace the identifier with
-> Term -- body in which to perform the replacements
-> Term
subst identifier term = go
where go (Id id') = if identifier == id' then term else Id id'
go (If t1 t2 t3) = If (go t1) (go t2) (go t3)
go …Run Code Online (Sandbox Code Playgroud) 有以下定义
type MyMap = Map[String, List[Map[Int, String]]]
Run Code Online (Sandbox Code Playgroud)
Map可以定义为更高的kinded类型吗?
这是我得到的:
spec :: Spec
spec = do
manager <- runIO newManager
it "foo" $ do
-- code that uses manager
it "bar" $ do
-- code that usees manager
Run Code Online (Sandbox Code Playgroud)
对于文档runIO表明,我或许应该使用beforeAll替代,因为我并不需要manager对构建规范的树,我只是需要它来运行每个测试,而在我的使用情况下,它的所有份额对他们来说是更好的同一个经理而不是创造每个测试都有一个新的.
如果您不需要IO操作的结果来构造spec树,则beforeAll可能更适合您的用例.
beforeAll :: IO a -> SpecWith a -> Spec
Run Code Online (Sandbox Code Playgroud)
但我无法弄清楚如何从测试中访问管理器.
spec :: Spec
spec = beforeAll newManager go
go :: SpecWith Manager
go = do
it "foo" $ do
-- needs "manager" in scope
it "bar" $ do
-- …Run Code Online (Sandbox Code Playgroud) 假设我有一些通用功能
genericFunc :: a -> b
genericFunc x = doSomeHardWork
Run Code Online (Sandbox Code Playgroud)
但对于特定类型,可以采用更有效的方式genericFunc.
genericFunc :: ParticularType -> b
genericFunc x = doSomeEasyWork
Run Code Online (Sandbox Code Playgroud)
将这两个函数体组合成相同的最佳方法是什么genericFunc,这样当使用ParticularType它时,它会doSomeEasyWork,但是当用于其他类型时,它会是doSomeHardWork什么?我特别排除了使用不同名称或不同模块的选项.
我相信这可以通过类型类来完成,但我对使用语言编译指示的解决方案更感兴趣.我有一个模糊的暗示,这可以用语言编译,但我不知道如何.如果您比较和对比这些方法和/或任何其他可能的方法,奖励积分.
使用ReadArgs包,它似乎不支持单参数情况.
{-# LANGUAGE ScopedTypeVariables #-}
import ReadArgs (readArgs)
main = do
(foo :: Int) <- readArgs
print foo
Run Code Online (Sandbox Code Playgroud)
错误是(使用版本1.0时):
No instance for (ReadArgs.ArgumentTuple Int)
arising from a use of `readArgs'
Run Code Online (Sandbox Code Playgroud)
我的问题是双重的:
readArgs工作怎么样?NB版1.1的ReadArgs消除了这个"错误"; 看评论.
haskell ×9
list ×2
arrows ×1
comparison ×1
datetime ×1
function ×1
functor ×1
generics ×1
hspec ×1
idiomatic ×1
io ×1
monads ×1
recursion ×1
scala ×1
type-kinds ×1
type-safety ×1
types ×1
unit-testing ×1