在阅读Haskell for the Good的剪辑时,我发现了以下情况:
treeInsert :: (Ord a) => a -> Tree a -> Tree a
treeInsert x EmptyTree = singleton x
treeInsert x (Node a left right)
| x == a = Node x left right
| x < a = Node a (treeInsert x left) right
| x > a = Node a left (treeInsert x right)
Run Code Online (Sandbox Code Playgroud)
如果我们只是重用给定的Tree,那对性能不是更好x == a
吗?
treeInsert :: (Ord a) => a -> Tree a -> Tree a
treeInsert x …
Run Code Online (Sandbox Code Playgroud) 在Applicative
深入研究的同时,我来到了Traversable
.虽然我已经Foldable
从LYHGG知道了,但我还没有见过前者,所以我开始阅读关于Traversable的Haskell wiki.
在阅读它时,我理解为什么它Foldable.fold
是平行的Traversable.sequenceA
并且Foldable.foldMap
是平行的Traversable.traverse
.
我也看到每个Traversable
也是a Foldable
和a Functor
,sequenceA
并且traversal
彼此有默认实现:
traverse f = sequenceA . fmap f
sequenceA = traverse id
Run Code Online (Sandbox Code Playgroud)
所以,正如我在LYHGG中看到的那样,它foldMap
是一个最小的完整定义Foldable
,我认为,它是平行的traverse
,所以fold
(它是平行的sequenceA
)也是一个最小的完整定义(它不是)... Foldable
是不是Functor
喜欢Traversable
的,所以我们不能申请这个:
foldMap f = fold . fmap f
fold = foldMap id -- this is ok
Run Code Online (Sandbox Code Playgroud)
为什么不是每Foldable
一个 …
在制作我的自定义时Either
,Functor
为了理解更清晰的类型和类型类,我发现了以下情况:
Functor
module Functor (Functor, fmap) where
import Prelude hiding(Functor, fmap)
class Functor f where
fmap :: (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)
Either
module Either(Either(..)) where
import Prelude hiding(Either(..), Functor, fmap)
data Either a b = Left a | Right b deriving(Show)
instance Functor (Either a) where
fmap f (Right x) = Right (f x)
fmap _ (Left x) = Left x
Run Code Online (Sandbox Code Playgroud)
上面显示的代码编译得很好但是,如果我将其更改为使用id
,则无法编译:
instance Functor (Either a) where
fmap f …
Run Code Online (Sandbox Code Playgroud) 在阅读关于MonadPlus的Haskell Wikibook时,我发现以下函数基本上采用a 和a 并且如果这样的char与字符串头相等则返回:Char
String
Just (char,tail)
Nothing
char :: Char -> String -> Maybe (Char, String)
char c s = do
let (c':s') = s
if c == c' then Just (c, s') else Nothing
Run Code Online (Sandbox Code Playgroud)
并且他们解释说let (c':s') = s
不会产生异常,因为它在一个do
块中会评估Nothing
模式何时失败,但事实并非如此,因为当我尝试它时:
*Main> char 'a' ""
*** Exception: exercice2.hs:5:7-17: Irrefutable pattern failed for pattern (c' : s')
Run Code Online (Sandbox Code Playgroud)
所以我不得不重写它:
char' :: Char -> String -> Maybe (Char, String)
char' _ [] = …
Run Code Online (Sandbox Code Playgroud) 我已经使用了Network.Wai.Middleware.Cors
's simpleCors
,它可以正常处理GET
请求,但是当我尝试发出POST
请求时,出现以下问题
OPTIONS /users
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Status: 400 Bad Request 0.032443s
Run Code Online (Sandbox Code Playgroud)
我能够使其工作的唯一方法是simpleCors
从以下部分中删除Application.hs
-- | Convert our foundation to a WAI Application by calling @toWaiAppPlain@ and
-- applying some additional middlewares.
makeApplication :: App -> IO Application
makeApplication foundation = do
logWare <- makeLogWare foundation
-- Create the WAI application and apply middlewares
appPlain <- toWaiAppPlain foundation
return $ logWare $ defaultMiddlewaresNoLogging $ simpleCors $ appPlain
Run Code Online (Sandbox Code Playgroud)
并添加 OPTIONS 方法响应
optionsNewUserR :: …
Run Code Online (Sandbox Code Playgroud) 此函数可以在无限关联列表上工作,很容易找出原因:
findKey :: (Eq k) => k -> [(k,v)] -> Maybe v
findKey key [] = Nothing
findKey key ((k,v):xs) = if key == k
then Just v
else findKey key xs
Run Code Online (Sandbox Code Playgroud)
当它找到键时,它返回Just v
,停止递归.现在看看另一个实现:
findKey' :: (Eq k) => k -> [(k,v)] -> Maybe v
findKey' key = foldr (\(k,v) acc -> if key == k then Just v else acc) Nothing
Run Code Online (Sandbox Code Playgroud)
编译器/解释器如何知道当密钥与k匹配时,它可以返回它?
*Main> findKey' 1 $ zip [1..] [1..]
Run Code Online (Sandbox Code Playgroud)
回报 Just 1
当它发现时key == k
,它返回 …
在寻找Polyvariadic函数示例时,我发现了这个资源: StackOverflow:如何创建polyvariadic haskell函数?,有一个这样的答案片段:
class SumRes r where
sumOf :: Integer -> r
instance SumRes Integer where
sumOf = id
instance (Integral a, SumRes r) => SumRes (a -> r) where
sumOf x = sumOf . (x +) . toInteger
Run Code Online (Sandbox Code Playgroud)
然后我们可以使用:
*Main> sumOf 1 :: Integer
1
*Main> sumOf 1 4 7 10 :: Integer
22
*Main> sumOf 1 4 7 10 0 0 :: Integer
22
*Main> sumOf 1 4 7 10 2 5 8 22 :: Integer
59 …
Run Code Online (Sandbox Code Playgroud) fold
在深入研究折叠的普遍性和表现力的教程时,
我发现了一个惊人的foldl
使用定义foldr
:
-- I used one lambda function inside another only to improve reading
foldl :: (b -> a -> b) -> b -> [a] -> b
foldl f z xs = foldr (\x g -> (\a -> g (f a x))) id xs z
Run Code Online (Sandbox Code Playgroud)
在了解了正在发生的事情后,我想我甚foldr
至可以用来定义foldl'
,这将是这样的:
foldl' :: (b -> a -> b) -> b -> [a] -> b
foldl' f z xs = foldr (\x g -> (\a -> …
Run Code Online (Sandbox Code Playgroud) 我怎样才能像这样插值:
{-# LANGUAGE QuasiQuotes #-}
import Text.RawString.QQ
myText :: Text -> Text
myText myVariable = [r|line one
line two
line tree
${ myVariable }
line five|]
myText' :: Text
myText' = myText "line four"
Run Code Online (Sandbox Code Playgroud)
${ myVariable }
作为文字打印,而不是插值,在这种情况下我可以做类似的事情来插值吗?
在下面的代码中,我不得不使用elem'
而不是简单的elem
,因为 prelude 已经有一个函数elem
,我如何elem
在声明 Tree 模块时使用,避免冲突??
module Tree(Tree(..), singleton, insert, elem') where
data Tree a = Empty | Node a (Tree a) (Tree a) deriving (Show)
singleton :: a -> Tree a
singleton a = Node a Empty Empty
insert :: (Ord a) => a -> Tree a -> Tree a
insert e Empty = singleton e
insert e tree@(Node e2 left right)
| e == e2 = tree
| e > e2 …
Run Code Online (Sandbox Code Playgroud) haskell ×10
fold ×2
performance ×2
recursion ×2
typeclass ×2
applicative ×1
constructor ×1
cors ×1
currying ×1
do-notation ×1
foldable ×1
functor ×1
module ×1
namespaces ×1
polyvariadic ×1
quasiquotes ×1
request ×1
rest ×1
traversable ×1
yesod ×1