考虑以下Haskell代码.
data Keypress = Keypress Int Char
getSeq :: Keypress -> [Char]
getSeq (Keypress i c) = replicate i c
Run Code Online (Sandbox Code Playgroud)
有没有办法以getSeq无点形式写作?
getSeq它的定义与模式匹配非常相似,似乎可能有某种方法可以使用currying或monads或其他东西来避免指定i和c参数.但是,由于模式匹配,我认为pointfree.io无法解析无点输出getSeq.
可能吗?
ama*_*loy 16
它通常很有用,特别是对于具有多个构造函数的递归数据类型,用于定义一个catamorphism,一种在为每个可能的构造函数赋予一个函数时折叠数据结构的方法.
例如,对于Boolcatamorphism是
bool :: a -> a -> Bool -> a
bool x _ False = x
bool _ y True = y
Run Code Online (Sandbox Code Playgroud)
因为Either它是
either :: (a -> c) -> (b -> c) -> Either a b -> c
either f g (Left x) = f x
either f g (Right x) = g x
Run Code Online (Sandbox Code Playgroud)
更高级的catamorphism是列表之一,你可能已经看过:foldr!
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f init [] = init
foldr f init (x:xs) = f x (foldr f init xs)
Run Code Online (Sandbox Code Playgroud)
我们通常不会这样想(或者至少我没有),但它foldr是一个catamorphism:它处理模式匹配并递归地为你解构列表,只要你为找到的值提供"处理程序"两个构造函数[a]:
[],根本不需要参数:只是一个类型的值b(x:xs).这种情况采用一个参数表示x列表的头部,一个参数表示递归地折叠尾部的结果,类型的值b.对于只有一个构造函数的类型,catamorphism不太令人兴奋,但我们可以轻松地为您的Keypress类型定义一个:
key :: (Int -> Char -> a) -> Keypress -> a
key f (Keypress x c) = f x c
Run Code Online (Sandbox Code Playgroud)
在某种程度上,catamorphism允许您抽象出函数定义的模式匹配部分,之后您可以只使用不需要直接触及底层数据类型的函数.
定义了一般有用的功能一次,你可以多次使用它来实现你心中所需的任何无点功能.在你的情况下,你可以简单地写
getSeq :: Keypress -> [Char]
getSeq = key replicate
Run Code Online (Sandbox Code Playgroud)
dfe*_*uer 12
如上所述,没有.但如果你愿意,你可以解决这个问题:
data Keypress = Keypress
{ count :: Int
, char :: Char }
Run Code Online (Sandbox Code Playgroud)
然后
getSeq p = replicate (count p) (char p)
Run Code Online (Sandbox Code Playgroud)
那可以转换成
getSeq = replicate <$> count <*> char
Run Code Online (Sandbox Code Playgroud)
你不能在没有一点样板的情况下做到这一点,但lens可以为你生成那个样板,所以这可能就像你要得到的那样接近.
使用makePrismsfrom Control.Lens.TH将生成一个Iso,实质上是单构造函数数据类型上的第一类模式匹配.方便Iso的是,s是双向的,所以你可以使用view它们(获取值,如模式匹配)和review它们(将值重新放入,就像正常使用构造函数一样).
使用makePrisms和view,可以以getSeq无点的方式编写:
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
data Keypress = Keypress Int Char
makePrisms ''Keypress
getSeq :: Keypress -> [Char]
getSeq = uncurry replicate . view _Keypress
Run Code Online (Sandbox Code Playgroud)
这是否更好?不知道.你的代码中的模式匹配看起来很好,但是如果你已经使用lens了,那么这个版本可能会更适合你.