是否可以以无点形式编写模式匹配函数?

mhe*_*rzl 8 haskell

考虑以下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或其他东西来避免指定ic参数.但是,由于模式匹配,我认为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)


Ale*_*ing 5

你不能在没有一点样板的情况下做到这一点,但lens可以为你生成那个样板,所以这可能就像你要得到的那样接近.

使用makePrismsfrom Control.Lens.TH将生成一个Iso,实质上是单构造函数数据类型上的第一类模式匹配.方便Iso的是,s是双向的,所以你可以使用view它们(获取值,如模式匹配)和review它们(将值重新放入,就像正常使用构造函数一样).

使用makePrismsview,可以以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了,那么这个版本可能会更适合你.